题解
对于任何一个粘液块s而言,要么是从左边被吞并,要么是从右边被吞并,根据对称性,两边的决策是一样的,因此先考虑右边
对于被右边吞并而言,有以下几个特征
1.起始粘液一定是吞掉了s右边一整块连续的粘液
2.右边区间一定存在大小不同的相邻粘液,这样才能发动吞并
3.由一二猜想,只要存在不同的相邻粘液,这一片区间上的粘液都会被吞并至只剩下一个粘液
证明:
假如只存在一个不同相邻粘液
最大的吞并比他小的-->原来大的比同伴大-->吞并同伴
存在两个及以上同理
4.因此我猜想,对于右边区间而言,存在不同相邻粘液块且区间和大于s的最小区间就是答案
开始证明
运用反证法:如果该区间不是最小区间,那么区间缩小,区间和会减小以至于可能小于s,也可能不存在相同相邻粘液,与题意不符,得证
然后很容易发现区间和具有单调性,是否存在不同相邻粘液也有单调性(不会减小)
因此二分
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll pres[300005]={0};
ll sufs[300005]={0};
ll a[300005]={0};
ll prech[300005]={0};
ll sufch[300005]={0};
ll press(ll l,ll r,ll x)
{
r++;
l--;
ll i=l;
if(a[i]<a[i+1])return i+1;
while(l+1<r)
{
ll mid=(l+r)/2;
if(pres[mid]-pres[i]>a[i]&&prech[mid]-prech[i+1]>0)
r=mid;
else l=mid;
}
return r;
}
ll sufss(ll l,ll r,ll x)
{
l--;
r++;
ll i=r;
if(a[i-1]>a[i])return i-1;
while(l+1<r)
{
ll mid=(l+r)/2;
if(sufs[mid]-sufs[i]>a[i]&&sufch[mid]-sufch[i-1]>0)
l=mid;
else r=mid;
}
return l;
}
int main()
{
ll t;
cin>>t;
while(t--)
{
ll n;
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
pres[i]=pres[i-1]+a[i];
if(i!=1)prech[i]=prech[i-1]+(a[i]!=a[i-1]);
}
sufs[n]=a[n];
sufch[n]=0;
for(ll i=n-1;i>=1;i--)
{
sufs[i]=sufs[i+1]+a[i];
sufch[i]=sufch[i+1]+(a[i]!=a[i+1]);
}
for(ll i=1;i<=n;i++)
{
if(i==1)
{
ll r=press(2,n,a[1]);
if(r!=n+1) cout<<r-i<<" ";
else printf("-1 ");
}
else if(i==n)
{
ll l=sufss(1,n-1,a[1]);
if(l!=0) cout<<i-l<<" ";
else printf("-1 ");
}
else
{
ll r=press(i+1,n,a[i]);
ll l=sufss(1,i-1,a[i]);
if(l!=0&&r!=n+1)cout<<min(i-l,r-i)<<" ";
else if(l!=0) cout<<i-l<<" ";
else if(r!=n+1) cout<<r-i<<" ";
else printf("-1 ");
}
}
puts("");
}
return 0;
}
标签:sufch,--,ll,Slimes,mid,区间,粘液
From: https://www.cnblogs.com/pure4knowledge/p/18041273