zoukankan      html  css  js  c++  java
  • bzoj3786: 星系探索

    Description

    物理学家小C的研究正遇到某个瓶颈。

    他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。

    我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.

    对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.

    每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。

    但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。

    有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。

    现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。

    Input

    第一行一个整数n,表示星系的星球数。

    接下来n-1行每行一个整数,分别表示星球2-n的依赖星球编号。

    接下来一行n个整数,表示每个星球在时刻0时的初始能量系数wi.

    接下来一行一个整数m,表示事件的总数。

    事件分为以下三种类型。

    (1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.

    (2)"C xi yi"表示星球xi的依赖星球变为了星球yi.

    (3)"F pi qi"表示星球pi能量激发,常数为qi.

    Output

    对于每一个事件类型为Q的事件,输出一行一个整数,表示此次实验的收集器最终能量。

    Sample Input

    3
    1
    1
    4 5 7
    5
    Q 2
    F 1 3
    Q 2
    C 2 3
    Q 2

    Sample Output

    9
    15
    25

    HINT

    n<=100000,m<=300000,1<di,xi<=n,wi,qi<=100000.保证操作合法。注意w_i>=0

    Source

    By 佚名上传


    solution

    欧拉序+splay

    子树修改很难实现啊,怎么办呢?

    任神犇:欧拉序,第一次的记为正,第二次记为负,这样子维护前缀和就可以了。

    orz!!

    如神犇所说,按欧拉序为下标建splay,支持区间修改,区间交换。

    当时想了很久都在想一个问题:我区间都换了,欧拉序也变了,那怎么才能把点找出来呢?

    首先,明确:

    tr[x]维护着欧拉序为x的答案,这是不会变的。

    而树结构的改变,意味着欧拉序的改变。

    也就是我们已知欧拉序,就可以取出一个点(虽然我不知道它在树的哪里)

    那我沿着这个点往根跳,就可以知道有多少个点比他小,也就是它排在第几位了

    然后就很方便啦。

    注意:

    1.欧拉序下标最好从2开始,不然很麻烦

    2.因为要严格按欧拉序建树,建时直接就是tr[mid]=W[mid]..

    3.注意w为0的情况

    4,swap取L[y]时要推标记(kth)

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define maxn 200005 
    #define ll long long
    #define inf 1e9
    using namespace std;
    int n,m,head[maxn],L[maxn],R[maxn],w[maxn],W[maxn],tot;
    int sc=1,root;
    struct node{
    	int v,nex;
    }e[maxn];
    struct no{
    	int ch[2],f,tp,sz;
    	ll v,bj,sum,stp;
    }tr[maxn];
    void lj(int t1,int t2){
    	e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
    }
    void dfs(int k){
    	L[k]=++sc;w[sc]=(W[k]!=0)?W[k]:inf;
    	for(int i=head[k];i;i=e[i].nex){
    		dfs(e[i].v);
    	}
    	R[k]=++sc;w[sc]=(W[k]!=0)?-W[k]:-inf;
    }
    int get(int x){
    	return tr[tr[x].f].ch[1]==x;
    }
    void wh(int k){
    	if(!k)return;
    	int ls=tr[k].ch[0],rs=tr[k].ch[1];
    	tr[k].sum=tr[ls].sum+tr[rs].sum+tr[k].v;
    	tr[k].stp=tr[ls].stp+tr[rs].stp+tr[k].tp;
    	tr[k].sz=tr[ls].sz+tr[rs].sz+1;
    }
    void update(int k,ll v){
    	if(!k)return;
    	tr[k].bj+=v;tr[k].sum+=tr[k].stp*v;
    	tr[k].v+=tr[k].tp*v;
    }
    void down(int k){
    	if(tr[k].bj){
    		update(tr[k].ch[0],tr[k].bj);
    		update(tr[k].ch[1],tr[k].bj);
    		tr[k].bj=0;
    	}
    }
    int build(int fa,int l,int r){
    	if(l>r)return 0;
    	int mid=l+r>>1,k=mid;
    	tr[k].f=fa;tr[k].v=tr[k].sum=(w[k]!=inf&&w[k]!=-inf)?w[k]:0;
    	tr[k].tp=tr[k].stp=(w[k]>0?1:-1);
    	tr[k].ch[0]=build(k,l,mid-1);
    	tr[k].ch[1]=build(k,mid+1,r);
    	wh(k);return k;
    }
    int find(int x){// Å·À­ÐòxÊǵڼ¸´óµÄÊý 
    	int sum=tr[tr[x].ch[0]].sz;
    	while(x!=root){
    		if(get(x))sum+=tr[tr[tr[x].f].ch[0]].sz+1;
    		x=tr[x].f;
    	}
    	return sum+1;
    }
    int Kth(int x){// µÚx´óÊÇË­ 
    	int k=root;
    	while(1){
    		down(k);
    		//cout<<k<<' '<<x<<endl;
    		int ls=tr[k].ch[0];
    		if(tr[ls].sz>=x)k=ls;
    		if(tr[ls].sz==x-1)return k;
    		if(tr[ls].sz<x-1)x-=tr[ls].sz+1,k=tr[k].ch[1];
    	}
    }
    void rotate(int x){
    	int y=tr[x].f,z=tr[y].f;
    	int wx=get(x),wy=get(y);
    	tr[z].ch[wy]=x;tr[x].f=z;
    	tr[y].ch[wx]=tr[x].ch[wx^1];tr[tr[x].ch[wx^1]].f=y;
    	tr[x].ch[wx^1]=y;tr[y].f=x;
    	wh(y),wh(x);
    }
    void splay(int x,int g){
    	while(tr[x].f!=g){
    		int y=tr[x].f,z=tr[y].f;
    		if(z!=g)rotate(get(x)==get(y)?y:x);
    		rotate(x);
    	}
    	if(!g)root=x;
    }
    
    void print_tr(int k){
    	if(!k)return;
    	down(k);
    	print_tr(tr[k].ch[0]);
    	printf("k:%d v:%d sum:%d tp:%d sz:%d f:%d
    ",k,tr[k].v,tr[k].sum,tr[k].tp,tr[k].sz,tr[k].f);
    	print_tr(tr[k].ch[1]);
    }
    int main(){
    	cin>>n;
    	for(int i=2,t;i<=n;i++)scanf("%d",&t),lj(t,i);
      	for(int i=1;i<=n;i++)scanf("%d",&W[i]);
      	dfs(1);
      	//for(int i=1;i<=n;i++)cout<<L[i]<<' '<<R[i]<<endl; 
      	root=build(0,1,n+n+2);
      	
      	scanf("%d",&m);
      	for(int i=1,x,y;i<=m;i++){
      		char op;scanf(" %c",&op);
      		if(op=='Q'){
      			scanf("%d",&x);
    			int a=Kth(find(L[x])+1);
    			//cout<<"a "<<a<<' '<<x<<' '<<L[x]<<' '<<find(L[x])<<endl;
    			splay(a,0);//print_tr(root);
    			printf("%lld
    ",tr[tr[root].ch[0]].sum);
    		}
      		if(op=='C'){
      			scanf("%d%d",&x,&y);
      			int a=Kth(find(L[x])-1),b=Kth(find(R[x])+1);
      			//cout<<a<<' '<<b<<endl;
      			splay(a,0);splay(b,a);
      			//print_tr(root);
      			int t=tr[tr[root].ch[1]].ch[0];
      			tr[tr[root].ch[1]].ch[0]=0;
    			wh(tr[root].ch[1]),wh(root);
      			a=Kth(find(L[y])),b=Kth(find(L[y])+1);
      			splay(a,0);splay(b,a);
      			tr[tr[root].ch[1]].ch[0]=t;tr[t].f=tr[root].ch[1];
      			wh(tr[root].ch[1]),wh(root);
    		}
      		if(op=='F'){
      			scanf("%d%d",&x,&y);
      			int a=Kth(find(L[x])-1),b=Kth(find(R[x])+1);
      			//cout<<"a b:"<<a<<' '<<b<<endl;
      			
      			splay(a,0);splay(b,a);
      			int t=tr[tr[root].ch[1]].ch[0];
      			update(t,y);
    			//print_tr(root);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    PAT (Advanced Level) 1060. Are They Equal (25)
    PAT (Advanced Level) 1059. Prime Factors (25)
    PAT (Advanced Level) 1058. A+B in Hogwarts (20)
    PAT (Advanced Level) 1057. Stack (30)
    PAT (Advanced Level) 1056. Mice and Rice (25)
    PAT (Advanced Level) 1055. The World's Richest (25)
    PAT (Advanced Level) 1054. The Dominant Color (20)
    PAT (Advanced Level) 1053. Path of Equal Weight (30)
    PAT (Advanced Level) 1052. Linked List Sorting (25)
    PAT (Advanced Level) 1051. Pop Sequence (25)
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358745.html
Copyright © 2011-2022 走看看