zoukankan      html  css  js  c++  java
  • BZOJ1500: [NOI2005]维修数列 Splay维护序列

    //#include<bits/stdc++.h>  
    //#pragma comment(linker, "/STACK:1024000000,1024000000")   
    #include<stdio.h>  
    #include<algorithm>  
    #include<queue>  
    #include<string.h>  
    #include<iostream>  
    #include<math.h>                    
    #include<set>  
    #include<map>  
    #include<vector>  
    #include<iomanip> 
    #include<bitset>
    using namespace std;         //
    
    #define ll long long  
    #define pb push_back  
    #define FOR(a) for(int i=1;i<=a;i++) 
    #define sqr(a) (a)*(a)
    #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
    ll qp(ll a,ll b,ll mod){
    	ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
    }
    struct DOT{int x;int y;};
    const int dx[4]={0,0,-1,1};
    const int dy[4]={1,-1,0,0};
    const int inf=0x3f3f3f3f;  
    const ll mod=1e9+7;
    
    const int maxn=5e5+6;
    
    int n,m;
    int a[maxn];
    
    int rt=0;
    int c[maxn][2],parent[maxn];
    int val[maxn],size[maxn];
    int lx[maxn],rx[maxn],mx[maxn],sum[maxn];
    int tag[maxn],rev[maxn];	
    int id[maxn];
    queue<int>Q;
    
    inline void pushup(int x){
    	int l=c[x][0],r=c[x][1];
    	size[x]=size[l]+size[r]+1;						//子树大小
    	sum[x]=sum[l]+sum[r]+val[x];					//区间和
    	mx[x]=max(max(mx[r],mx[l]),val[x]+rx[l]+lx[r]);	//最大子段和
    	lx[x]=max(lx[l],sum[l]+val[x]+lx[r]);			//最大前缀
    	rx[x]=max(rx[r],sum[r]+val[x]+rx[l]);			//最大后缀
    }
    void pushdown(int x){
    	int l=c[x][0],r=c[x][1];
    	if(tag[x]){
    		tag[x]=rev[x]=0;
    		if(l)tag[l]=1,val[l]=val[x],sum[l]=val[x]*size[l];
    		if(r)tag[r]=1,val[r]=val[x],sum[r]=val[x]*size[r];
    		if(val[x]>=0){
    			if(l)lx[l]=rx[l]=mx[l]=sum[l];
    			if(r)lx[r]=rx[r]=mx[r]=sum[r];
    		}else{
    			if(l)lx[l]=rx[l]=0;mx[l]=val[x];
    			if(r)lx[r]=rx[r]=0,mx[r]=val[x];
    		}
    	}
    	if(rev[x]){
    		rev[x]=0;rev[l]^=1;rev[r]^=1;
    		swap(lx[l],rx[l]);swap(lx[r],rx[r]);
    		swap(c[l][0],c[l][1]);swap(c[r][0],c[r][1]);
    	}
    }
    void rotate(int x,int &k){
    	int y=parent[x],z=parent[y],d=c[y][1]==x;
    	if(y==k)k=x;else c[z][c[z][1]==y]=x;parent[x]=z;
    	c[y][d]=c[x][d^1];parent[c[x][d^1]]=y;
    	c[x][d^1]=y;parent[y]=x;
    	pushup(y);pushup(x);
    }
    void splay(int x,int &k){
    	while(x!=k){
    		int y=parent[x],z=parent[y];
    		if(y!=k) (c[y][0]==x^c[z][0]==y)?rotate(x,k):rotate(y,k);
    		rotate(x,k);
    	}
    }
    
    inline int find(int x,int k){
    	pushdown(x);
    	int lc=c[x][0],rc=c[x][1];
    	if(k>size[lc]+1)return find(rc,k-size[lc]-1);
    	else if(k<=size[lc])return find(lc,k);
    	else return x;
    }
    inline int Split(int l,int r){
    	int x=find(rt,l);
    	int y=find(rt,r);
    
    	splay(x,rt);splay(y,c[x][1]);
    	return c[y][0];
    }
    
    void init(){for(int i=n+3;i<maxn;i++)Q.push(i);}
    
    inline void recycle(int x){
    	int &l=c[x][0],&r=c[x][1];
    	if(l)recycle(l);if(r)recycle(r);
    	Q.push(x);
    	parent[x]=l=r=tag[x]=rev[x]=0;
    }
    void erase(int l,int r){
    	int x=Split(l,r),y=parent[x];
    	recycle(x);
    	c[y][0]=0;pushup(y);pushup(parent[y]);
    }
    
    void build(int l,int r,int f){
    	if(l>r)return;
    	int m=l+r>>1,now=id[m],pa=id[f];
    	val[now]=a[m];parent[now]=pa;
    	c[pa][m>=f]=now;
    	if(l==r){
    		mx[now]=sum[now]=val[now];
    		lx[now]=rx[now]=max(0,val[now]);
    		size[now]=1;
    		return;
    	}
    	build(l,m-1,m);build(m+1,r,m);
    	pushup(now);
    }
    void insert(int l,int tot){
    	for(int i=1;i<=tot;i++)scanf("%d",&a[i]);
    	for(int i=1;i<=tot;i++)id[i]=Q.front(),Q.pop();
    	build(1,tot,0);
    	int z=id[1+tot>>1],x=find(rt,l+1),y=find(rt,l+2);	//标号右移
    	splay(x,rt);splay(y,c[x][1]);
    	parent[z]=y;c[y][0]=z;
    	pushup(y);pushup(x);
    }
    int query(int l,int r){
    	int x=Split(l,r);
    	return sum[x];
    }
    void rever(int l,int r){
    	int x=Split(l,r),y=parent[x];
    	if(!tag[x]){
    		rev[x]^=1;
    		swap(c[x][0],c[x][1]);
    		swap(lx[x],rx[x]);
    		pushup(y);pushup(parent[y]);
    	}
    }
    void update(int l,int r,int v){
    	int x=Split(l,r),y=parent[x];
    	val[x]=v;tag[x]=1;sum[x]=size[x]*v;
    	if(v>=0)lx[x]=rx[x]=mx[x]=sum[x];
    	else lx[x]=rx[x]=0,mx[x]=v;
    	pushup(y);pushup(parent[y]);
    }
    
    char s[20];
    int main(){
    	scanf("%d%d",&n,&m);
    	mx[0]=a[1]=a[n+2]=-inf;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i+1]);
    	}
    	for(int i=1;i<=n+2;i++)id[i]=i;
    
    	init();
    	build(1,n+2,0);rt=n+3>>1;
    
    	for(int i=1;i<=m;i++){
    		scanf("%s",s);
    		if(s[2]=='X')printf("%d
    ",mx[rt]);
    		else{
    			int k,tot;scanf("%d",&k);scanf("%d",&tot);
    			if(s[2]=='S')insert(k,tot);
    			if(s[2]=='L')erase(k,k+tot+1);
    			if(s[2]=='K'){int x;scanf("%d",&x);update(k,k+tot+1,x);}
    			if(s[2]=='V')rever(k,k+tot+1);
    			if(s[2]=='T')printf("%d
    ",query(k,k+tot+1));
    		}
    	}
    }
    

    通过split提取目标区间,由于旋转到根影响的父节点就2个

    支持O(logn)区间反转,O(元素个数)加入元素

    回收节点编号的操作挺棒的,以后不用担心数组版数据结构溢编号了

  • 相关阅读:
    将数据挂载到 docker 容器中的3种方式:volume、bind mount、tmpfs
    kubectl 常用命令
    Kubernetes 知识点
    spring boot 学习资料
    docker 常见系统镜像
    docker 的前台模式和后台模式
    Docker容器里的进程为什么要前台运行?相同的问题:docker运行apache为什么带FOREGROUND参数?docker运行nginx为什么带`daemon off`参数?
    spring cloud 各核心组件作用
    nginx 镜像使用说明
    optimization.splitChunks 中,chunks 的3个值:all、async、initial 的含义
  • 原文地址:https://www.cnblogs.com/Drenight/p/8611200.html
Copyright © 2011-2022 走看看