• 【题解】[SHOI2015]脑洞治疗仪


    Problem

    ( ext{Solution:})

    这题唯一需要学习 or 复习的点就是它的查询了。

    这东西一眼的维护左右最长连续的 (0) 的长度就做完了。标记什么的都很简单。代码量略微大一点。

    注意在询问的时候:

    如果完全在左右区间,就分别递归。

    否则,我们还需要考虑跨越区间的最值。那应该是:从当前向左右两侧延申最长距离之和。

    这个自己推一下就行了。

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=5e5+10;
    int ls[MAXN],rs[MAXN],sum[MAXN];
    int node,opt;
    int llen[MAXN],rlen[MAXN],mlen[MAXN];
    int L[MAXN],R[MAXN],tag[MAXN],n,m,rt;
    inline int read() {
    	int s=0;
    	char ch=getchar();
    	while(!isdigit(ch)) ch=getchar();
    	while(isdigit(ch)) {
    		s=s*10-48+ch;
    		ch=getchar();
    	}
    	return s;
    }
    inline int Len(int x) {
    	return R[x]-L[x]+1;
    }
    inline int Min(int x,int y) {
    	return x<y?x:y;
    }
    inline int Max(int x,int y) {
    	return x>y?x:y;
    }
    inline void pushup(int x) {
    	sum[x]=sum[ls[x]]+sum[rs[x]];
    	llen[x]=llen[ls[x]];
    	if(llen[ls[x]]==Len(ls[x]))
    		llen[x]+=llen[rs[x]];
    	
    	rlen[x]=rlen[rs[x]];
    	if(rlen[x]==Len(rs[x]))
    		rlen[x]+=rlen[ls[x]];
    	
    	mlen [ x ] = Max ( mlen [ ls [ x ] ] , mlen [ rs [ x ] ] ) ;
    	mlen [ x ] = Max ( mlen [ x ] , rlen [ ls [ x ] ] + llen [ rs [ x ] ] ) ;
    }
    void build(int &x,int l,int r) {
    	if(!x)x=++node;
    	L[x]=l;
    	R[x]=r;
    	tag[x]=-1;
    	if(l==r) {
    		rlen[x]=llen[x]=mlen[x]=0;
    		sum[x]=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls[x],l,mid);
    	build(rs[x],mid+1,r);
    	pushup(x);
    }
    inline void pushdown(int x) {
    	if(tag[x]!=-1) {
    		int p=tag[x];
    		tag[x]=-1;
    		tag[ls[x]]=tag[rs[x]]=p;
    		sum[ls[x]]=p*Len(ls[x]);
    		sum[rs[x]]=p*Len(rs[x]);
    		if(p==0) {
    			llen[ls[x]]=rlen[ls[x]]=mlen[ls[x]]=Len(ls[x]);
    			llen[rs[x]]=rlen[rs[x]]=mlen[rs[x]]=Len(rs[x]);
    		} else {
    			llen[ls[x]]=rlen[ls[x]]=mlen[ls[x]]=0;
    			llen[rs[x]]=rlen[rs[x]]=mlen[rs[x]]=0;
    		}
    	}
    }
    int query(int x,int l,int r) {
    	if(L[x]>=l&&R[x]<=r)return sum[x];
    	pushdown(x);
    	int mid=(L[x]+R[x])>>1,res=0;
    	if(l<=mid)res=query(ls[x],l,r);
    	if(mid<r)res+=query(rs[x],l,r);
    	pushup(x);
    	return res;
    }
    void change(int x,int l,int r,int v) {
    	if(L[x]>=l&&R[x]<=r) {
    		tag[x]=v;
    		sum[x]=v*Len(x);
    		llen[x]=rlen[x]=mlen[x]=(1-v)*Len(x);
    		return;
    	}
    	pushdown(x);
    	int mid=(L[x]+R[x])>>1;
    	if(l<=mid)change(ls[x],l,r,v);
    	if(mid<r)change(rs[x],l,r,v);
    	pushup(x);
    }
    int query_max(int x,int l,int r) {
    	if(L[x]>=l&&R[x]<=r)return mlen[x];
    	pushdown(x);
    	int mid=(L[x]+R[x])>>1;
    	if(r<=mid)return query_max(ls[x],l,r);
    	else if(l>mid)return query_max(rs[x],l,r);
    	return Max(Max(query_max(ls[x],l,r),query_max(rs[x],l,r)),Min(rlen[ls[x]],L[rs[x]]-l)+Min(llen[rs[x]],r-R[ls[x]]));
    }
    int querypos(int l,int r,int s) {
    	int L=l,R=r,ans=l;
    	while(L<=R){
    		int mid=(L+R)>>1;
    		if(mid-l+1-(query(rt,l,mid))<=s)ans=mid,L=mid+1;
    		else R=mid-1;
    	}
    	return ans;
    }
    //void dfs(int x){
    //	pushdown(x);
    //	if(!ls[x]&&!rs[x])printf("%d ",sum[x]);
    //	if(ls[x])dfs(ls[x]);
    //	if(rs[x])dfs(rs[x]);
    //}
    inline void write(int x){
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    int main() {
    	n=read();
    	m=read();
    	build(rt,1,n);
    	while(m--) {
    		opt=read();
    		int al=read(),ar=read(),bl,br;
    		if(opt==0)change(rt,al,ar,0);
    		else if(opt==1) {
    			bl=read();
    			br=read();
    			int S=query(rt,al,ar);
    			change(rt,al,ar,0);
    			int P=query(rt,bl,br);
    			int cnt0=(br-bl+1)-P;
    			S=Min(S,cnt0);
    			if(S==0)continue;
    			int pos=querypos(bl,br,S);
    			change(rt,bl,pos,1);
    		} else write(query_max(rt,al,ar)),putchar('
    ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    探索需求14
    周总结5
    周总结4
    探索需求13
    Java——迭代器
    Java——Collection集合
    Java——包装类
    Java——Arrays
    Java——BigInteger、BigDecimal
    Java——System
  • 原文地址:https://www.cnblogs.com/h-lka/p/14965297.html
Copyright © 2020-2023  润新知