【lct】bzoj1036 [ZJOI2008]树的统计Count

题意:给你一棵树,点带权,支持三种操作:单点修改;询问链上和;询问链上max。

这里的Query操作用了与上一题不太一样的做法(上一题用那种做法,因为在边带权的情况下换根太困难啦):

  先ChangeRoot(U),然后Access(V),再Splay(V),询问V在辅助树中的左子树。

因为Splay的pushdown用了极为暴力的做法……故而跑得比原来写的链剖线段树慢一倍。不过常数不在意了。

#include<cstdio>
#include<iostream>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 30005
int fa[maxn],c[maxn][2],siz[maxn];
bool is_root[maxn],delta[maxn];
int val[maxn],totalval[maxn],maxv[maxn];
void Mark(int x){
    if(x){
        delta[x]^=1;
    }
}
void Maintain(int x)
{
    siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
    totalval[x]=totalval[c[x][0]]+totalval[c[x][1]]+val[x];
    maxv[x]=val[x];
    if(c[x][0]){
    	maxv[x]=max(maxv[x],maxv[c[x][0]]);
    }
    if(c[x][1]){
    	maxv[x]=max(maxv[x],maxv[c[x][1]]);
    }
}
void pushdown(int x){
    if(delta[x]){
        Mark(c[x][0]);
        Mark(c[x][1]);
        swap(c[x][0],c[x][1]);
        delta[x]=0;
    }
}
void Rotate(int x,bool flag)
{
    int y=fa[x];
    c[y][!flag]=c[x][flag];
    if(c[x][flag]){
    	fa[c[x][flag]]=y;
    }
    if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){
        c[fa[y]][c[fa[y]][1]==y]=x;
    }
    fa[x]=fa[y];
    c[x][flag]=y;
    fa[y]=x;
    if(is_root[y]){
    	is_root[y]=0;
    	is_root[x]=1;
    }
	Maintain(y);
	Maintain(x);
}
stack<int>st;
void Splay(int x)
{
	pushdown(x);
    if(!x || is_root[x]){
        return;
    }
	int U=x;
	while(!is_root[U]){
		st.push(U);
		U=fa[U];
	}
	st.push(U);
	while(!st.empty()){
		pushdown(st.top());
		st.pop();
	}
    int y;
    while(y=fa[x],(!is_root[x])){
        if(is_root[y]){
            Rotate(x,c[y][0]==x);
        }
        else{
            if((c[y][0]==x)==(c[fa[y]][0]==y)){
                Rotate(y,c[fa[y]][0]==y);
            }
            else{
                Rotate(x,c[y][0]==x);
                y=fa[x];
            }
            Rotate(x,c[y][0]==x);
        }
    }
	Maintain(x);
}
void Access(int x){
	int y;
	Splay(x);
	while(fa[x]){
		y=fa[x];
		Splay(y);
		Splay(x);
		if(c[y][1]){
			is_root[c[y][1]]=1;
		}
		is_root[x]=0;
		c[y][1]=x;
		Splay(x);
	}
	if(c[x][1]){
		is_root[c[x][1]]=1;
		c[x][1]=0;
	}
}
void ChangeRoot(int x){
	Access(x);
	Splay(x);
	Mark(x);
}
int QSum(int U,int V){
	ChangeRoot(U);
	Access(V);
	Splay(V);
	return val[V]+totalval[c[V][0]];
}
int QMax(int U,int V){
	ChangeRoot(U);
	Access(V);
	Splay(V);
	if(!c[V][0]){
		return val[V];
	}
	else{
		return max(val[V],maxv[c[V][0]]);
	}
}
int n,m;
int v[maxn<<1],nex[maxn<<1],first[maxn],e;
void AddEdge(int U,int V){
	v[++e]=V;
	nex[e]=first[U];
	first[U]=e;
}
int a[maxn];
void dfs(int U){
	siz[U]=1;
	is_root[U]=1;
	val[U]=totalval[U]=maxv[U]=a[U];
	for(int i=first[U];i;i=nex[i]){
		if(!siz[v[i]]){
			fa[v[i]]=U;
			dfs(v[i]);
		}
	}
}
int main(){
//	freopen("bzoj1036.in","r",stdin);
	char op[10];
	int x,y;
	scanf("%d",&n);
	for(int i=1;i<n;++i){
		scanf("%d%d",&x,&y);
		AddEdge(x,y);
		AddEdge(y,x);
	}
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	dfs(1);
	scanf("%d",&m);
	for(int i=1;i<=m;++i){
		scanf("%s%d%d",op,&x,&y);
		if(op[3]=='N'){
			Splay(x);
			val[x]=y;
			Maintain(x);
		}
		else if(op[3]=='M'){
			printf("%d\n",QSum(x,y));
		}
		else{
			printf("%d\n",QMax(x,y));
		}
	}
    return 0;
}
posted @ 2017-10-10 21:04  AutSky_JadeK  阅读(198)  评论(0编辑  收藏  举报
TVアニメ「Charlotte(シャーロット)」公式サイト TVアニメ「Charlotte(シャーロット)」公式サイト