CF1428Fフルーツシーケンス

解決策-CF1428 F \ mathrm {CF1428F}C F 1 4 2 8 F

トピックの意味

トピックポータル

S ol \ mathrm {Sol} S O L

11について検討する1貢献だけを数えます。

假设 a i = 1 a_i=1 A=1その後、連続した1 1はそれで終わります1の長さはllですl、次に[1、i − l] [1、il][ 1 l ]最も遠いjjを見つけるjaj = 1 a_j = 1を満たしますAJ=1そしてそれから始める111セグメントの長さL≤lL\ leq lLlラインセグメントツリーを使用して、間隔max⁡\ maxを維持できます。簡単に達成するための最大マーク。

jjが見つかったとしますjは、貢献に参加する方法を検討します。明らかに[j、i − l] [j、il][ j L ] llを追加するためのこのセグメントの貢献l[i − l + 1、i] [i-l + 1、i][私はl+1 i ]この間隔全体に11を追加します1(各添え字iiは個人として)。

したがって、間隔プラス、間隔最大⁡\ maxを維持するだけで済みますmaxで十分です。時間の複雑さO(nlog⁡n)O(n \ log n)O nlo gn

コード\ mathrm {Code} C O D E

const int N=5e5+5;

int n,m,tr[N*4],laz[N*4],tr2[N*4],tag[N*4];
int ans,las;
char a[N];

inline void pd(int x,int l,int r,int t1,int t2) 
{
    
    
	if(t1) tag[x]=0,tr[x]=(r-l+1)*t1,tr2[x]=laz[x]=t1;
	if(t2) tr[x]+=(r-l+1)*t2,tag[x]+=t2,tr2[x]+=t2; 
}

inline void pushdown(int x,int l,int r) 
{
    
    
	if(laz[x]||tag[x]) 
	{
    
    
		int mid=l+r>>1;
		pd(x<<1,l,mid,laz[x],tag[x]);
		pd(x<<1|1,mid+1,r,laz[x],tag[x]);
		laz[x]=tag[x]=0;
	}
}

inline int query(int x,int l,int r,int goal) 
{
    
    
	if(l==r) return l;
	int mid=l+r>>1;
	pushdown(x,l,r);
	if(tr2[x<<1|1]>=goal) return query(x<<1|1,mid+1,r,goal);
	else return query(x<<1,l,mid,goal);
}

inline void add(int x,int l,int r,int ll,int rr,int v) 
{
    
    
	if(ll>r||rr<l) return;
	if(ll<=l&&r<=rr) 
	{
    
    
		tr[x]+=(r-l+1)*v,tag[x]+=v,tr2[x]+=v;
		return;
	}
	int mid=l+r>>1;
	pushdown(x,l,r);
	add(x<<1,l,mid,ll,rr,v),add(x<<1|1,mid+1,r,ll,rr,v);
	tr[x]=tr[x<<1]+tr[x<<1|1];
	tr2[x]=max(tr2[x<<1],tr2[x<<1|1]);
}

inline void Add(int x,int l,int r,int ll,int rr,int v) 
{
    
    
	if(ll>r||rr<l) return;
	if(ll<=l&&r<=rr)
	{
    
    
		tr[x]=(r-l+1)*v,tr2[x]=v,laz[x]=v;
		tag[x]=0;
		return;
	}
	int mid=l+r>>1;
	pushdown(x,l,r);
	Add(x<<1,l,mid,ll,rr,v),Add(x<<1|1,mid+1,r,ll,rr,v);
	tr[x]=tr[x<<1]+tr[x<<1|1];
	tr2[x]=max(tr2[x<<1],tr2[x<<1|1]);
}

signed main()
{
    
    
	scanf("%d",&n);
	scanf("%s",a+1);
	For(i,1,n) 
	{
    
    
		if(a[i]=='1') 
		{
    
    
			if(!las) las=i;
			int can_reach=query(1,1,n,i-las+1); 
			add(1,1,n,las,i,1);
			if(can_reach<las) Add(1,1,n,can_reach,las-1,i-las+1);
		}
		else las=0;
		ans+=tr[1];
	}
	io.write(ans),puts("");
	return 0;
}

おすすめ

転載: blog.csdn.net/wangyiyang2/article/details/109147002