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

    题目

    一颗带点权的树,根为1,实现下列三种操作:

    • (Q x) 求点(x)到根的点权和
    • (C x y)(x)的父亲换成(y)
    • (F x y)(x)的子树中每个点的点权点权增加(y)

    分析

    写了一半发现lct做不了,因为有子树修改。然而zwl说,由于树的形态没有改变,可以通过维护lct的一些东西解决。toptree模板题,但是不会写。于是有一个神奇方法——dfs序(欧拉序)。我们把每个点的入栈和出栈时间用一个splay维护,那么就可以很方便的修改子树(splay标记),换父亲(区间移动)。现在问题是怎么求到根的点权和。这里有一个很精妙的做法:我们把入栈时的点设为正,出栈设为负,那么欧拉序前缀和就是点到根的点权和。因为如果已经出栈了的点是不在这个点到根的链上的。这样做就很简单了。

    代码

    一定要记得,splay在insert的时候是要不断下传标记的。一开始就这里错了。

    #include<cstdio>
    #include<algorithm>
    #include<cctype>
    #define F(x) for (giant i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v)
    using namespace std;
    typedef long long giant;
    giant read() {
    	giant x=0,f=1;
    	char c=getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const giant maxn=1e5+10;
    const giant inf=1e9+10;
    giant val[maxn],dft=1,first[maxn],second[maxn];
    struct node {
    	giant v,sum,fa,ch[2],sta,tag,gs,ps,ns;
    	bool inv;
    } t[maxn<<2];
    struct edge {
    	giant v,nxt;
    } e[maxn<<1];
    giant h[maxn],tot=0;
    void add(giant u,giant v) {
    	e[++tot]=(edge){v,h[u]};
    	h[u]=tot;
    }
    giant root;
    bool rson(giant x) {
    	return t[t[x].fa].ch[1]==x;
    }
    giant pos(giant x) {
    	giant now=x,ret=t[t[x].ch[0]].gs+1;
    	while (now) {
    		if (rson(now)) ret+=t[t[t[now].fa].ch[0]].gs+1;
    		now=t[now].fa;
    	}
    	return ret;
    }
    giant find(giant x) {
    	giant now=root;
    	while (true) {
    		giant tmp=t[t[now].ch[0]].gs+1;
    		if (x==tmp) return now; else
    		if (x>tmp) x-=tmp,now=t[now].ch[1]; else
    		if (x<tmp) now=t[now].ch[0];
    	}
    	return 0;
    }
    void doit(giant x,giant y) {
    	if (!x) return;
    	t[x].tag+=y;
    	t[x].v+=y;
    	t[x].sum+=(t[x].ps-t[x].ns)*y;
    }
    void push(giant x) {
    	if (!t[x].tag) return;
    	giant l=t[x].ch[0],r=t[x].ch[1];
    	if (l) doit(l,t[x].tag);
    	if (r) doit(r,t[x].tag);
    	t[x].tag=0;
    }
    void update(giant x) {
    	push(x);
    	t[x].gs=t[t[x].ch[0]].gs+t[t[x].ch[1]].gs+1;
    	t[x].ps=t[t[x].ch[0]].ps+t[t[x].ch[1]].ps+(t[x].sta==1);
    	t[x].ns=t[t[x].ch[0]].ns+t[t[x].ch[1]].ns+(t[x].sta==-1);
    	t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].v*t[x].sta;
    }
    void rotate(giant x) {
    	giant f=t[x].fa,d=rson(x),c=t[x].ch[d^1];
    	if (t[f].fa) t[t[f].fa].ch[rson(f)]=x;
    	if (c) t[c].fa=f;
    	t[x].fa=t[f].fa,t[f].fa=x,t[x].ch[d^1]=f,t[f].ch[d]=c;
    	update(f),update(x);
    }
    void down(giant x) {
    	if (t[x].fa) down(t[x].fa);
    	push(x);
    }
    void splay(giant x,giant d=0) {
    	down(x);
    	while (t[x].fa!=d) {
    		if (t[t[x].fa].fa==d) rotate(x); else {
    			if (rson(x)==rson(t[x].fa)) {
    				rotate(t[x].fa);
    				rotate(x);
    			} else {
    				rotate(x);
    				rotate(x);
    			}
    		}
    	}
    	if (!d) root=x;
    }
    void insert(giant p,giant x) {
    	if (!root) {
    		update(x);
    		t[root=x].gs=1;
    		return;
    	}
    	giant now=root;
    	while (now) {
    		push(now);
    		giant tmp=t[t[now].ch[0]].gs+1;
    		giant &a=t[now].ch[p>=tmp];
    		p-=(p>=tmp)*tmp;
    		if (a) now=a; else {
    			a=x;
    			t[x].fa=now;
    			update(x);
    			break;
    		}
    	}
    	for (;now;now=t[now].fa) update(now);
    	splay(x);
    }
    giant range(giant x,giant y) {
    	giant px=pos(x);
    	giant bf=find(px-1);
    	splay(bf);
    	giant py=pos(y);
    	giant af=find(py+1);
    	splay(af,bf);
    	return t[af].ch[0];
    }
    void dfs(giant x,giant fa) {
    	first[x]=++dft;
    	t[dft].sta=1;
    	t[dft].v=val[x];
    	insert(dft-1,dft);
    	F(x) if (v!=fa) dfs(v,x);
    	second[x]=++dft;
    	t[dft].sta=-1;
    	t[dft].v=val[x];
    	insert(dft-1,dft);
    }
    int main() {
    	#ifndef ONLINE_JUDGE
    		freopen("test.in","r",stdin);
    		freopen("my.out","w",stdout);
    	#endif
    	giant n=read();
    	for (giant i=2;i<=n;++i) {
    		giant x=read();
    		add(i,x),add(x,i);
    	}
    	for (giant i=1;i<=n;++i) val[i]=read();
    	insert(0,1); // because of this node, all the ids have to be increased by one.
    	dfs(1,0);
    	insert(n*2+1,n*2+2);
    	giant m=read();
    	while (m--) {
    		static char o[3];
    		scanf("%s",o);
    		if (o[0]=='Q') {
    			giant x=read();
    			giant now=range(2,first[x]);
    			printf("%lld
    ",t[now].sum);
    			splay(now);
    		} else if (o[0]=='C') {
    			giant x=read(),y=read();
    			giant nx=range(first[x],second[x]);
    			giant f=t[nx].fa;
    			bool rs=rson(nx);
    			t[f].ch[rs]=0,t[nx].fa=0;
    			update(f);
    			insert(pos(first[y]),nx);
    		} else if (o[0]=='F') {
    			giant x=read(),y=read();
    			giant now=range(first[x],second[x]);
    			doit(now,y);
    			splay(now);
    		}
    	}
    }
    
  • 相关阅读:
    学习c++一点一滴mbstowcs
    学习c++一点一滴读取网络适配器信息
    学习c++一点一滴资源dll的封装和调用
    存储过程
    学习c++一点一滴c++builder 导出excel
    线程池
    Jacob操作office文档(Word,PPT,Excel)
    域名转让
    线程交互
    Scala中的语言特性是如何实现的(2)
  • 原文地址:https://www.cnblogs.com/owenyu/p/6724693.html
Copyright © 2011-2022 走看看