zoukankan      html  css  js  c++  java
  • 【[SHOI2015]脑洞治疗仪】

    我太sb啦

    合并的时候又漏了,又漏了,又漏了

    我个sb

    这是个板子题,并不知道为什么SHOI2015会考这么板子的题,但是我又sb了,又sb了,又sb了,又没有1A

    显然我是凉了

    这道题有三个操作

    1. 区间清零

    2. 将一个区间清零,之后补到另一个区间去,但是有可能补不满

    3. 询问一个区间内最大全零子串

    显然这都是线段树的板子操作,对于维护这种区间最长的连续的子串,我们只需要多维护两个数组(rc[i],lc[i]),分别表示一个区间内从左开始和从右开始的最长子串,于是就可以合并啦

    之后第二个操作看起来很唬人,但是其实也非常板子,我们要找最长的区间,这个区间内的0的个数必须小于等于那个清零了的区间里原来的1的个数

    这显然是满足单调性的,我们显然可以将这个区间二分出来

    于是这里需要二分一下,同时二分的过程中线段树查询一下一个区间内1的个数来判断,所以操作2的复杂度是(O(log^2n))

    看起来(O(mlog^2n))加上线段树的大常数跑(200000)有些危险,但是人要有信仰

    之后最sb的是我写错的地方,就是(pushup)还有(query)合并区间的时候,如果一个区间的左半部分全是0,那么这个区间的从左开始的最长的全0子串肯定可以延伸到右端去,所以这里不能简单地(lc[i]=lc[i<<1])了,我们需要判断一下在合并

    可见我有多么sb

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define maxn 200005
    #define max(a,b) ((a)>(b)?(a):(b))
    struct TREENODE
    {
    	int ll,rr,len;
    };
    int l[maxn<<2],r[maxn<<2],tag[maxn<<2];
    int d[maxn<<2],ans[maxn<<2],lc[maxn<<2],rc[maxn<<2];
    int n,m;
    inline int read()
    {
    	char c=getchar();
    	int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9')
    	  x=(x<<3)+(x<<1)+c-48,c=getchar();
    	return x;
    }
    inline void pushup(int i)
    {
    	d[i]=d[i<<1]+d[i<<1|1];
    	if(lc[i<<1]!=r[i<<1]-l[i<<1]+1) lc[i]=lc[i<<1];
    		else lc[i]=lc[i<<1]+lc[i<<1|1];
    	if(rc[i<<1|1]!=r[i<<1|1]-l[i<<1|1]+1) rc[i]=rc[i<<1|1];
    		else rc[i]=rc[i<<1|1]+rc[i<<1];
    	ans[i]=max(max(ans[i<<1],ans[i<<1|1]),rc[i<<1]+lc[i<<1|1]);
    }
    void build(int x,int y,int i)
    {
    	l[i]=x;
    	r[i]=y;
    	tag[i]=-1;
    	if(x==y) 
    	{
    		d[i]=1;
    		rc[i]=lc[i]=0;
    		return;
    	}
    	int mid=l[i]+r[i]>>1;
    	build(x,mid,i<<1);
    	build(mid+1,y,i<<1|1);
    	pushup(i);
    }
    inline void pushdown(int i)
    {
    	if(tag[i]==-1) return;
    	if(tag[i]==1)
    	{
    		d[i<<1]=r[i<<1]-l[i<<1]+1;
    		d[i<<1|1]=r[i<<1|1]-l[i<<1|1]+1;
    		ans[i<<1|1]=ans[i<<1]=0;
    		rc[i<<1|1]=rc[i<<1]=0;
    		lc[i<<1]=lc[i<<1|1]=0;
    		tag[i<<1|1]=tag[i<<1]=1;
    		tag[i]=-1;
    	}
    	if(!tag[i])
    	{
    		d[i<<1|1]=d[i<<1]=0;
    		rc[i<<1|1]=lc[i<<1|1]=ans[i<<1|1]=r[i<<1|1]-l[i<<1|1]+1;
    		rc[i<<1]=lc[i<<1]=ans[i<<1]=r[i<<1]-l[i<<1]+1;
    		tag[i<<1]=tag[i<<1|1]=0;
    		tag[i]=-1;
    	}
    }
    void change(int x,int y,int v,int i)
    {
    	if(x<=l[i]&&y>=r[i])
    	{
    		d[i]=v*(r[i]-l[i]+1);
    		tag[i]=v;
    		if(!v) lc[i]=rc[i]=ans[i]=r[i]-l[i]+1;
    		else lc[i]=rc[i]=ans[i]=0;
    		return;
    	}
    	pushdown(i);
    	int mid=l[i]+r[i]>>1;
    	if(y<=mid) change(x,y,v,i<<1);
    	else if(x>mid) change(x,y,v,i<<1|1);
    	else change(x,y,v,i<<1),change(x,y,v,i<<1|1);
    	pushup(i);
    }
    int ask(int x,int y,int i)
    {
    	if(x<=l[i]&&y>=r[i]) return d[i];
    	pushdown(i);
    	int mid=l[i]+r[i]>>1;
    	if(y<=mid) return ask(x,y,i<<1);
    	if(x>mid) return ask(x,y,i<<1|1);
    	return ask(x,y,i<<1)+ask(x,y,i<<1|1);
    }
    TREENODE query(int x,int y,int i)
    {
    	if(x<=l[i]&&y>=r[i]) return (TREENODE){lc[i],rc[i],ans[i]};
    	pushdown(i);
    	int mid=l[i]+r[i]>>1;
    	if(y<=mid) return query(x,y,i<<1);
    	if(x>mid) return query(x,y,i<<1|1);
    	TREENODE lson=query(x,y,i<<1),rson=query(x,y,i<<1|1);
    	int LEN=max(max(lson.len,rson.len),lson.rr+rson.ll);
    	int LL,RR;
    	if(lson.ll==mid-l[i]+1) LL=lson.ll+rson.ll;
    		else LL=lson.ll;
    	if(rson.rr==r[i]-mid) RR=rson.rr+lson.rr;
    		else RR=rson.rr;
    	return (TREENODE){LL,RR,LEN};
    }
    int main()
    {
    	n=read();
    	m=read();
    	build(1,n,1);
    	int x,y,opt,xx,yy;
    	while(m--)
    	{
    		opt=read();
    		x=read(),y=read();
    		if(opt==1) xx=read(),yy=read();
    		if(!opt) change(x,y,0,1);
    		if(opt==1)
    		{
    			int tot=ask(x,y,1);
    			if(!tot) continue;
    			change(x,y,0,1);
    			int L=1,R=yy-xx+1,ty;
    			while(L<=R)
    			{
    				int mid=L+R>>1;
    				if(mid-ask(xx,xx+mid-1,1)<=tot) ty=mid,L=mid+1;
    				else R=mid-1;
    			}
    			change(xx,xx+ty-1,1,1);
    		}
    		if(opt==2) printf("%d
    ",query(x,y,1).len);
    	}
    	return 0;
    }
    
  • 相关阅读:
    例图作业
    冲刺第二天
    Day9
    Day8
    Day7
    Day6
    Day5
    Day4
    Day2
    第四次作业——个人作业——软件案例分析
  • 原文地址:https://www.cnblogs.com/asuldb/p/10206246.html
Copyright © 2011-2022 走看看