zoukankan      html  css  js  c++  java
  • bzoj 1858: [Scoi2010]序列操作【线段树】

    合并中间那块的时候没取max……WAWAWA
    在线段树上维护一堆东西,分别是len区间长度,sm区间内1的个数,ll0区间从左开始最长连续0,ml0区间中间最长连续0,rl0区间从右开始最长连续0,ll1区间从左开始最长连续1,ml1区间中间最长连续1,rl1区间从右开始最长连续1(起始这六个东西可以存成三个数组,这样操作起来比较方便),lz标记区间赋值(没有赋值的时候为-1),f标记区间取反
    仔细思考一下优先级,赋值>取反,所以lz标记不为-1时,f标记为0
    sm,len的和并很好说,以下x表示0或1,llx的合并是左儿子的llx,如果左儿子全是x的话就加上右儿子的llx,rlx同理,mlx是max(左儿子的rlx+右儿子的llx,左儿子的mlx,右儿子的mlx)
    注意细节不要手残打错!

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=100005;
    int n,m,a[N];
    struct xds
    {
    	int l,r,len,sm,ll[2],ml[2],rl[2],f,lz;
    }t[N<<2];
    struct qwe
    {
    	int l,m,r;
    	qwe(int L=0,int M=0,int R=0)
    	{
    		l=L,m=M,r=R;
    	}
    };
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void ud(int ro)
    {
    	t[ro].sm=t[ro<<1].sm+t[ro<<1|1].sm;
    	t[ro].ll[0]=t[ro<<1].ll[0]+((t[ro<<1].sm==0)?t[ro<<1|1].ll[0]:0);
    	t[ro].ml[0]=max(t[ro<<1].rl[0]+t[ro<<1|1].ll[0],max(t[ro<<1].ml[0],t[ro<<1|1].ml[0]));
    	t[ro].rl[0]=t[ro<<1|1].rl[0]+((t[ro<<1|1].sm==0)?t[ro<<1].rl[0]:0);
    	t[ro].ll[1]=t[ro<<1].ll[1]+((t[ro<<1].sm==t[ro<<1].len)?t[ro<<1|1].ll[1]:0);
    	t[ro].ml[1]=max(t[ro<<1].rl[1]+t[ro<<1|1].ll[1],max(t[ro<<1].ml[1],t[ro<<1|1].ml[1]));
    	t[ro].rl[1]=t[ro<<1|1].rl[1]+((t[ro<<1|1].sm==t[ro<<1|1].len)?t[ro<<1].rl[1]:0);
    }
    void pd(int ro)
    {
    	if(t[ro].lz!=-1)
    	{
    		t[ro<<1].lz=t[ro].lz,t[ro<<1].f=0;
    		t[ro<<1].sm=t[ro].lz?t[ro<<1].len:0;
    		t[ro<<1].ll[t[ro].lz]=t[ro<<1].ml[t[ro].lz]=t[ro<<1].rl[t[ro].lz]=t[ro<<1].len;
    		t[ro<<1].ll[t[ro].lz^1]=t[ro<<1].ml[t[ro].lz^1]=t[ro<<1].rl[t[ro].lz^1]=0;
    		t[ro<<1|1].lz=t[ro].lz,t[ro<<1|1].f=0;
    		t[ro<<1|1].sm=t[ro].lz?t[ro<<1|1].len:0;
    		t[ro<<1|1].ll[t[ro].lz]=t[ro<<1|1].ml[t[ro].lz]=t[ro<<1|1].rl[t[ro].lz]=t[ro<<1|1].len;
    		t[ro<<1|1].ll[t[ro].lz^1]=t[ro<<1|1].ml[t[ro].lz^1]=t[ro<<1|1].rl[t[ro].lz^1]=0;
    		t[ro].lz=-1;
    	}
    	if(t[ro].f)
    	{
    		t[ro<<1].f^=1;
    		swap(t[ro<<1].ll[0],t[ro<<1].ll[1]);
    		swap(t[ro<<1].ml[0],t[ro<<1].ml[1]);
    		swap(t[ro<<1].rl[0],t[ro<<1].rl[1]);
    		t[ro<<1].sm=t[ro<<1].len-t[ro<<1].sm;
    		if(t[ro<<1].lz!=-1)
    			t[ro<<1].lz^=1,t[ro<<1].f=0;
    		t[ro<<1|1].f^=1;
    		swap(t[ro<<1|1].ll[0],t[ro<<1|1].ll[1]);
    		swap(t[ro<<1|1].ml[0],t[ro<<1|1].ml[1]);
    		swap(t[ro<<1|1].rl[0],t[ro<<1|1].rl[1]);
    		t[ro<<1|1].sm=t[ro<<1|1].len-t[ro<<1|1].sm;
    		if(t[ro<<1|1].lz!=-1)
    			t[ro<<1|1].lz^=1,t[ro<<1|1].f=0;
    		t[ro].f=0;
    	}
    }
    void build(int ro,int l,int r)
    {
    	t[ro].l=l,t[ro].r=r,t[ro].len=r-l+1,t[ro].lz=-1;
    	if(l==r)
    	{
    		t[ro].sm=a[l];
    		t[ro].ll[a[l]]=t[ro].ml[a[l]]=t[ro].rl[a[l]]=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ro<<1,l,mid);
    	build(ro<<1|1,mid+1,r);
    	ud(ro);
    }
    void update(int ro,int l,int r,int v)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    	{
    		t[ro].lz=v,t[ro].f=0;
    		t[ro].sm=v?t[ro].len:0;
    		t[ro].ll[v]=t[ro].ml[v]=t[ro].rl[v]=t[ro].len;
    		t[ro].ll[v^1]=t[ro].ml[v^1]=t[ro].rl[v^1]=0;
    		return;
    	}
    	pd(ro);
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		update(ro<<1,l,r,v);
    	else if(l>mid)
    		update(ro<<1|1,l,r,v);
    	else
    		update(ro<<1,l,mid,v),update(ro<<1|1,mid+1,r,v);
    	ud(ro);
    }
    void fan(int ro,int l,int r)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    	{
    		t[ro].f^=1;
    		swap(t[ro].ll[0],t[ro].ll[1]);
    		swap(t[ro].ml[0],t[ro].ml[1]);
    		swap(t[ro].rl[0],t[ro].rl[1]);
    		t[ro].sm=t[ro].len-t[ro].sm;
    		if(t[ro].lz!=-1)
    			t[ro].lz^=1,t[ro].f=0;
    		return;
    	}
    	pd(ro);
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		fan(ro<<1,l,r);
    	else if(l>mid)
    		fan(ro<<1|1,l,r);
    	else
    		fan(ro<<1,l,mid),fan(ro<<1|1,mid+1,r);
    	ud(ro);
    }
    int ques(int ro,int l,int r)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    		return t[ro].sm;
    	pd(ro);
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		return ques(ro<<1,l,r);
    	else if(l>mid)
    		return ques(ro<<1|1,l,r);
    	else
    		return ques(ro<<1,l,mid)+ques(ro<<1|1,mid+1,r);
    }
    qwe lian(int ro,int l,int r)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    		return qwe(t[ro].ll[1],t[ro].ml[1],t[ro].rl[1]);
    	pd(ro);
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		return lian(ro<<1,l,r);
    	else if(l>mid)
    		return lian(ro<<1|1,l,r);
    	else
    	{
    		int len1=mid-l+1,len2=r-mid,ll,ml,rl;
    		qwe a=lian(ro<<1,l,mid),b=lian(ro<<1|1,mid+1,r);
    		ll=a.l+((a.l==len1)?b.l:0);
    		ml=max(a.r+b.l,max(a.m,b.m));
    		rl=b.r+((b.r==len2)?a.r:0);
    		return qwe(ll,ml,rl);
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read();
    	build(1,1,n);
    	while(m--)
    	{
    		int o=read(),l=read()+1,r=read()+1;
    		if(o==0)
    			update(1,l,r,0);
    		else if(o==1)
    			update(1,l,r,1);
    		else if(o==2)
    			fan(1,l,r);
    		else if(o==3)
    			printf("%d
    ",ques(1,l,r));
    		else
    			printf("%d
    ",lian(1,l,r).m);
    	}
    	return 0;
    }
    
  • 相关阅读:
    C#中二进制,八进制,十六进制到十进制的相互转换
    Mac装Win10后没有无线网络的处理
    U盘容纳不了大于4G的文件比如ISO文件咋办?
    经典游戏“大富翁4”存档文件修改器Rich4Editor下载
    向C#的选项卡中添加自定义窗体
    C#对二进制文件的特定位置进行读写小结
    抗战剧中最耐看的《我的团长我的团》,最后结尾依然有神剧的影子
    绝大多数人努力程度之低,根本轮不上拼天赋
    ZT:与其怨天尤人,不如全力以赴;若想改变世界,你必须先从改变自己开始!
    java基础学习_多线程02_多线程、设计模式_day24总结
  • 原文地址:https://www.cnblogs.com/lokiii/p/9639411.html
Copyright © 2011-2022 走看看