• P4146 序列终结者(Splay树)


    给出一个初始为0的序列。

    询问区间最大值,并同时支持区间修改和区间翻转。

    就正常模仿线段树,给Splay打懒标记即可。

    巨大的坑就是要保证虚拟节点,0,1,n+2不对答案产生影响。
    这里把他们的权值和区间值全置为负无穷。

    //区间修改
    //区间反转
    //区间求MAX
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+10;
    const long long inf=1e18;
    int rt,fa[maxn],ch[maxn][2],sz[maxn];
    int lz[maxn];//区间翻转标记
    long long add_lz[maxn];//区间修改标记
    long long c[maxn];//保存区间最大值
    long long w[maxn];
    int tot;
    long long a[maxn];
    struct Splay {
    	void maintain (int x) {
    		sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;
    		c[x]=max(w[x],max(c[ch[x][0]],c[ch[x][1]]));
    	}
    	void pushdown (int x) {
    		if (!x) return;
    		if (lz[x]) {
    			swap(ch[x][0],ch[x][1]);
    			lz[ch[x][0]]^=lz[x];
    			lz[ch[x][1]]^=lz[x];
    			lz[x]=0;
    		}
    		if (add_lz[x]) {
    			if (ch[x][0]){
    				c[ch[x][0]]+=add_lz[x];
    				w[ch[x][0]]+=add_lz[x];
    				add_lz[ch[x][0]]+=add_lz[x];
    			}
    			if (ch[x][1]){
    				c[ch[x][1]]+=add_lz[x];
    				w[ch[x][1]]+=add_lz[x];
    				add_lz[ch[x][1]]+=add_lz[x];
    			}
    			add_lz[x]=0;
    		}
    	}
    	bool get (int x) {
    		return x==ch[fa[x]][1];
    	}
    	void rotate (int x) {
    		pushdown(x);
    		pushdown(fa[x]);
    		int y=fa[x];
    		int z=fa[y];
    		int chk=get(x);
    		ch[y][chk]=ch[x][chk^1];
    		if (ch[x][chk^1]) {
    			fa[ch[x][chk^1]]=y;
    		}
    		ch[x][chk^1]=y;
    		fa[y]=x;
    		fa[x]=z;
    		if (z) {
    			ch[z][y==ch[z][1]]=x;
    		}
    		maintain(x);
    		maintain(y);
    	}
    	void splay (int x,int ed) {
    		for (int f=fa[x];(f=fa[x])!=ed;rotate(x)) {
    			if (fa[f]!=ed) {
    				rotate(get(x)==get(f)?f:x);
    			}
    		}
    		if (ed==0) rt=x;
    	}
    	int build (int l,int r,int f) {
    		if (l>r) return 0;
    		int mid=(l+r)>>1;
    		int u=++tot;
    		fa[u]=f;
    		ch[u][0]=ch[u][1]=lz[u]=0;
    		sz[u]=1;
    		ch[u][0]=build(l,mid-1,u);
    		ch[u][1]=build(mid+1,r,u);
    		maintain(u);
    		return u;
    	}
    	int rk (int x) {
    		int cur=rt;
    		while (1) {
    			pushdown(cur);
    			if (x<=sz[ch[cur][0]]) {
    				cur=ch[cur][0];
    			}
    			else {
    				x-=sz[ch[cur][0]]+1;
    				if (!x) return cur;
    				cur=ch[cur][1];
    			}
    		}
    		return 0; 
    	}
    	void rev (int x,int y) {
    		int l=x-1;
    		int r=y+1;
    		l=rk(l);
    		r=rk(r);
    		splay(l,0);
    		splay(r,l);
    		int pos=ch[rt][1];
    		pos=ch[pos][0];
    		lz[pos]^=1;
    	}
    	void up (int x,int y,int v) {
    		int l=x-1;
    		int r=y+1;
    		l=rk(l);
    		r=rk(r);
    		splay(l,0);
    		splay(r,l);
    		int pos=ch[rt][1];
    		pos=ch[pos][0];
    		c[pos]+=v;
    		w[pos]+=v;
    		add_lz[pos]+=v;
    	}
    	long long query (int x,int y) {
    		int l=x-1;
    		int r=y+1; 
    		l=rk(l);
    		r=rk(r);
    		splay(l,0);
    		splay(r,l);
    		int pos=ch[rt][1];
    		pos=ch[pos][0];
    		return c[pos]; 
    	}
    }splay; 
    int main () {
    	
    	int n,m;
    	scanf("%d%d",&n,&m);
    	c[0]=w[0]=w[1]=w[n+2]=-inf;
    	rt=splay.build(1,n+2,0);
    	while (m--) {
    		int op;
    		scanf("%d",&op);
    		if (op==1) {
    			int l,r,v;
    			scanf("%d%d%d",&l,&r,&v);
    			l++,r++;
    			splay.up(l,r,v);
    		}
    		else if (op==2){
    			int l,r;
    			scanf("%d%d",&l,&r);
    			l++,r++;
    			splay.rev(l,r);
    		}
    		else {
    			int l,r;
    			scanf("%d%d",&l,&r);
    			l++,r++;
    			long long ans=splay.query(l,r);
    			printf("%lld
    ",ans);
    		}
    	}
    }
  • 相关阅读:
    Win7 IIS FTP
    (转)Windows平台下git中文乱码的问题
    (转)如何在MySql中记录SQL日志(例如Sql Server Profiler)
    (转)Mysql 使用
    Xcode 快捷键
    (转)xcode 4.2 新建工程模板详解
    解决apache的the requested operation has failed
    ANDROID 获取SD卡剩余容量
    (转)struct tm 的应用 了解strtok应用
    (转)Ubuntu建立PHP服务器(apache+php+mysql)
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/15085222.html
Copyright © 2020-2023  润新知