[BZOJ 2759] 一个动态树好题

这题确实很好.

题解方面,网上有许多不错的题解,所以就不说了.

这题很需要注意细节.

#include<cstdio>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define db long double 
#define pii pair<int,int>
#define pb push_back
#define FILE "dealing"
template<class T> inline bool cmin(T& a,T b){return a>b?a=b,true:false;}
template<class T> inline bool cmax(T& a,T b){return a<b?a=b,true:false;}
template<class T> inline T squ(T a){return a*a;}
const int maxn=210000+10,mod=10007,base=23;
int read(){
    int x=0,f=1,ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    return x*f;
}
struct Node{
	int y,next,v;
}e[maxn];int len,linkk[maxn];
void insert(int x,int y,int v){
	e[++len].y=y;
	e[len].next=linkk[x];
	linkk[x]=len;
	e[len].v=v;
}
int n,m;
int fa[maxn],sf[maxn],c[maxn][2];
bool isroot(int x){
	return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}

struct node{
	int k,b;
	node(int k=1,int b=0):k(k),b(b){}
}li[maxn],sum[maxn];
node operator+(const node& a,const node& b){
	node c;
	c.k=a.k*b.k%mod;
	c.b=(a.b*b.k%mod+b.b)%mod;
	return c;
}
void updata(int x){
	sum[x]=sum[c[x][0]]+li[x]+sum[c[x][1]];
}
void rotate(int x){
	int y=fa[x],z=fa[y],d=c[y][1]==x;
	if(!isroot(y))c[z][c[z][1]==y]=x;
	fa[y]=x;fa[x]=z;if(c[x][d^1])fa[c[x][d^1]]=y;
	c[y][d]=c[x][d^1],c[x][d^1]=y;
	updata(y);updata(x);
}
void splay(int x){
	if(!x)return;
	while(!isroot(x)){
		int y=fa[x],z=fa[y];
		if(!isroot(y)){
			if(c[y][1]==x^c[z][1]==y)rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
}
void access(int x){
	for(int t=0;x;t=x,x=fa[x]){
		splay(x);
		c[x][1]=t;
		updata(x);
	}
}
int root,vis[maxn];
void dfs(int x,int fa){
	vis[x]=1;
	for(int i=linkk[x];i;i=e[i].next){
		if(e[i].y==fa)continue;
		if(!vis[e[i].y])dfs(e[i].y,x);
		else root=x;
	}
}
int inv[maxn];
int getroot(int x){
	access(x);splay(x);
	while(c[x][0])x=c[x][0];
	return x;
}
int getl(int x){
	access(x);splay(x);
	x=c[x][0];while(c[x][1])x=c[x][1];
	return x;
}
int tk[maxn];
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read();
	up(i,1,n){
		li[i].k=read();
		fa[i]=read();
		li[i].b=read();
		sum[i]=li[i];
		insert(i,fa[i],1);
		insert(fa[i],i,-1);
		tk[i]=fa[i];
	}
	up(i,1,n){
		if(vis[i])continue;
		root=0;
		dfs(i,0);
		sf[root]=fa[root];
		fa[root]=0;
	}
	m=read();
	inv[0]=inv[1]=1;
	for(int i=2;i<mod;i++)inv[i]=(mod-(mod/i)*inv[mod%i]%mod)%mod;
	up(i,1,m){
		char s;
		scanf(" %c",&s);
		if(s=='A'){
			int x=read();
			int root=getroot(x),y=sf[root];
			access(y);splay(y);
			node b=sum[y];
			if(b.k==1){
				if(b.b==0)printf("%d\n",-2);
				else printf("-1\n");
			}
			else {
				int key=(mod-b.b)%mod*inv[(b.k-1+mod)%mod]%mod;
				access(x);splay(x);
				printf("%d\n",(sum[x].k*key%mod+sum[x].b)%mod);
			}
		}
		else {
			int x=read(),k=read(),p=read(),b=read();
			int ro=getroot(x);
			li[x]=node(k,b);
			updata(x);
			if(tk[x]==p)continue;
			tk[x]=p;
			if(ro==x){
				sf[ro]=0;
				int ro2=getroot(p);
				if(ro2==ro)sf[ro]=p;
				else {
					access(ro);splay(ro);
					fa[ro]=p;
				}
			}
			else {
				int w=getl(x);
				access(x);splay(w);
				c[w][1]=fa[x]=0;updata(w);
				int y=sf[ro];
				int ro2=getroot(y);
				if(ro2!=ro){
					access(ro);
					splay(ro);
					fa[ro]=y;
					sf[ro]=0;
				}
				int ro3=getroot(p);
				access(x);
				splay(x);
				if(ro3!=x)fa[x]=p;
				else sf[x]=p;
			}
		}
	}
	return 0;
}

  

posted @ 2017-05-15 21:21  CHADLZX  阅读(140)  评论(0编辑  收藏  举报