zoukankan      html  css  js  c++  java
  • 牛客小白月赛18 E.Forsaken的数列【Splay】

    传送门
    之前用 FhqTreap 写过,刚刚学了 splay,再用 splay 写一下。
    splay 比 FhqTreap 好的地方就是好写一点,但速度丢人。
    splay 处理区间问题,就每次将代表 l-1 位置的点甩到根,然后将代表 r+1 的点甩到根的右儿子,那么此时 r+1 的点的左子树就是要处理的区间。
    在指定位置插入数也是一个道理,将 pos-1 甩到根,pos 甩到根的右儿子,把新插入的点设为 pos 的左儿子即可。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=2e5+10;
    int read(){
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    int n,a[N];
    
    struct Splay{
    	int root,siz[N],fa[N],ch[N][2],tot;LL sum[N],val[N],tag[N];
    	int newnode(int x,int f){fa[++tot]=f;val[tot]=sum[tot]=x;siz[tot]=1;return tot;}
    	int relat(int p,int f){return ch[f][1]==p;}
    	void connect(int p,int f,int k){ch[f][k]=p;fa[p]=f;}
    	void pushup(int p){
    		siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+1;
    		sum[p]=sum[ch[p][0]]+sum[ch[p][1]]+val[p];
    	}
    	void pushdown(int id){
    		int ls=ch[id][0],rs=ch[id][1];
    		sum[ls]+=tag[id]*siz[ls];val[ls]+=tag[id];tag[ls]+=tag[id];
    		sum[rs]+=tag[id]*siz[rs];val[rs]+=tag[id];tag[rs]+=tag[id];
    		tag[id]=0;
    	}
    	void rotate(int p){
    		int f=fa[p],ff=fa[f],k=relat(p,f);
    		connect(ch[p][k^1],f,k);
    		connect(p,ff,relat(f,ff));
    		connect(f,p,k^1);
    		pushup(f);pushup(p);
    	}
    	void splay(int p,int top){
    		if(top==0) root=p;
    		while(fa[p]!=top){
    			int f=fa[p],ff=fa[f];
    			if(ff!=top) relat(p,f)^relat(f,ff)?rotate(p):rotate(f);
    			rotate(p);
    		}
    	}
    	int findpos(int k){
    		int p=root;
    		while(1){
    			if(tag[p]) pushdown(p);
    			if(k<=siz[ch[p][0]]) p=ch[p][0];
    			else if(k==siz[ch[p][0]]+1) break;
    			else k-=siz[ch[p][0]]+1,p=ch[p][1];
    		}
    		return p;
    	}
    	void insert(int k,int x=0){
    		int p=findpos(k),q=findpos(k+1);
    		splay(p,0);splay(q,p);
    		int id=newnode(x,q);
    		ch[q][0]=id;
    		splay(id,0);
    	}
    	void upd(int l,int r,int x){
    		int p=findpos(l),q=findpos(r+2);
    		splay(p,0);splay(q,p);
    		int id=ch[q][0];
    		sum[id]+=1ll*x*siz[id];val[id]+=x;tag[id]+=x;
    	}
    	LL ask(int l,int r){
    		int p=findpos(l),q=findpos(r+2);
    		splay(p,0);splay(q,p);
    		return sum[ch[q][0]];
    	}
    }spl;
    
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	for(int i=0;i<=n+1;i++){
    		int p=spl.newnode(a[i],i);
    		if(i) spl.ch[i][1]=p;
    		spl.splay(p,0);
    	}
    	int m=read();
    	while(m--){
    		int opt=read();
    		if(opt==1) {int pos=read();spl.insert(pos);}
    		else if(opt==2){
    			int l=read(),r=read(),x=read();
    			spl.upd(l,r,x);
    		}
    		else if(opt==3){
    			int l=read(),r=read();
    			printf("%lld
    ",spl.ask(l,r));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    fetch API 和 ajax
    java 通过数据库名获得 该数据所有的表名以及字段名、字段类型
    自定义注解,通过反射获得注解中的值(详细自定义注解解释)
    main方法中sleep
    eclipse中设置JVM内存
    命令java 找不到或无法加载主类
    windows下的命令
    mac terminal基本命令
    ThreadLocal 源码剖析
    SQL中的函数用法
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12691934.html
Copyright © 2011-2022 走看看