• Jzoj5662 尺树寸泓


    平衡树的问题,很容易想到中序遍历

    那么我们给每一个节点记录一下中序遍历中它子树所在的区间,一次旋转显然只会改变两个节点的值

    对于询问我们用线段树区间求积就可以了

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 200010
    #define M 1000000007
    #define LL long long
    #define mid (l+r>>1)
    #define ls l,mid,x<<1
    #define rs mid+1,r,x<<1|1
    using namespace std;
    int clk,n,m,l[N],r[N],v[N];
    int w[N],wl[N],wr[N],p[N],s[N],rk[N],rt;
    int T[N<<2];
    inline void ps(int x){
    	s[x]=(s[l[x]]+s[r[x]]+v[x])%M;
    	wl[x]=(l[x]?wl[l[x]]:rk[x]);
    	wr[x]=(r[x]?wr[r[x]]:rk[x]);
    }
    inline void dfs(int x){
    	if(l[x]) dfs(l[x]);
    	w[++clk]=x; rk[x]=clk;
    	if(r[x]) dfs(r[x]);
    	ps(x);
    }
    inline void build(int l,int r,int x){
    	if(l==r){ T[x]=s[w[l]]; return; }
    	build(ls);
    	build(rs);
    	T[x]=((LL)T[x<<1]*T[x<<1|1])%M;
    }
    inline void update(int l,int r,int x,int p,int k){
    	if(l==r){ T[x]=k; return; }
    	if(p<=mid) update(ls,p,k); else update(rs,p,k);
    	T[x]=((LL)T[x<<1]*T[x<<1|1])%M;
    }
    inline LL query(int l,int r,int x,int L,int R){
    	if(L<=l && r<=R) return T[x];
    	LL ans=1;
    	if(L<=mid) ans=ans*query(ls,L,R)%M;
    	if(mid<R) ans=ans*query(rs,L,R)%M;
    	return ans;
    }
    int main(){
    	freopen("splay.in","r",stdin);
    	freopen("splay.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d%d%d",v+i,l+i,r+i);
    		p[l[i]]=i; p[r[i]]=i;
    	}
    	for(int i=1;i<=n;++i) if(!p[i]) rt=i;
    	dfs(rt); 
    	build(1,n,1);
    	for(int o,x,y;m--;){
    		scanf("%d%d",&o,&x);
    		if(o==2) printf("%lld
    ",query(1,n,1,wl[x],wr[x]));
    		else{
    			if(!o&&l[x]){
    				y=l[x]; o=p[x];
    				l[x]=r[y]; r[y]=x; 
    				if(l[x]) p[l[x]]=x; p[x]=y; p[y]=o;
    				if(o){
    					if(l[o]==x) l[o]=y; else r[o]=y;
    				} else rt=y;
    				ps(x); ps(y);
    				update(1,n,1,rk[x],s[x]);
    				update(1,n,1,rk[y],s[y]);
    			} else if(o&&r[x]){
    				y=r[x]; o=p[x];
    				r[x]=l[y]; l[y]=x;
    				if(r[x]) p[r[x]]=x; p[x]=y; p[y]=o;
    				if(o){
    					if(l[o]==x) l[o]=y; else r[o]=y;
    				} else rt=y;
    				ps(x); ps(y);
    				update(1,n,1,rk[x],s[x]);
    				update(1,n,1,rk[y],s[y]);
    			}
    		}
    	}
    } 

  • 相关阅读:
    3.23.谷歌中国搜索关闭的日子
    在Fedora下成功将Vim打造成适用于C/C++的IDE
    有关内存DC和双缓冲位图的问题汇总
    [转]阶乘 n! 末尾 0 的个数
    [转]各种排序算法
    [转]使用CEGUI的Editbox进行中文输入
    [转]ASP.NET中文件上传下载方法集合
    背包问题的c++解法
    [转]经典C/C++算法
    [转]编写自己的MSN机器人
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477107.html
Copyright © 2020-2023  润新知