[bzoj3531][Sdoi2014][旅行] (主席树+树链剖分)

Description

 S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
    在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
    由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。    为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

Input

    输入的第一行包含整数N,Q依次表示城市数和事件数。
    接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
    接下来N-1行每行两个整数x,y表示一条双向道路。
    接下来Q行,每行一个操作,格式如上所述。

Output

    对每个QS和QM事件,输出一行,表示旅行者记下的数字。

Sample Input

5 6
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4

Sample Output

8
9
11
3

HINT

 

N,Q < =10^5    , C < =10^5


 数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

 

Solution

水题

用主席树做一做就好

#include <stdio.h>
#include <string.h>
#define RG register
#define N 100010
#define dmax(a,b) ((a)>(b)?(a):(b))
template<class Type> inline void R(RG Type &x) {
	RG int c=getchar();for(;c<48||c>57;c=getchar());
	for(x=0;c>47&&c<58;x=(x<<1)+(x<<3)+c-48,c=getchar()); }
bool vis[N];int n,q,w[N],c[N],tim,fa[N],dep[N],sz[N],lef[N],top[N],hso[N],tot,root[N];
struct Pt {
	int v; Pt *nt; }*fi[N],me[N<<1],*tp=me;
struct Ch {
	int ls,rs,mx,su; }tr[N*40];
inline void link(RG int x,RG int y) {
	*++tp=(Pt){y,fi[x]},fi[x]=tp;
	*++tp=(Pt){x,fi[y]},fi[y]=tp; }
void dfsi(RG int x){
	vis[x]=sz[x]=1;
	for(RG Pt *it=fi[x];it;it=it->nt)
		if(!vis[it->v])
			dep[it->v]=dep[x]+1,
			fa[it->v]=x,
			dfsi(it->v),
			sz[x]+=sz[it->v],
			hso[x]=sz[it->v]>sz[hso[x]]?it->v:hso[x];
}
void dfsm(RG int x){
	vis[x]=0;
	top[x]=x==hso[fa[x]]?top[fa[x]]:x;
	lef[x]=++tim;
	if(hso[x]){
		dfsm(hso[x]);
		for(RG Pt *it=fi[x];it;it=it->nt)
			if(vis[it->v])
				dfsm(it->v);
	}
}
inline int lca(RG int x,RG int y){
	while(top[x]^top[y])
		dep[top[x]]>dep[top[y]]?
		x=fa[top[x]]:
		y=fa[top[y]];
	return dep[x]<dep[y]?x:y;
}
inline void Pu(RG int pr) {
	tr[pr].mx=dmax(tr[tr[pr].ls].mx,tr[tr[pr].rs].mx);
	tr[pr].su=tr[tr[pr].ls].su+tr[tr[pr].rs].su; }
void modify(RG int &pr,RG int x,RG int y,RG int po,RG int nu){
	if(!pr)pr=++tot;
	if(!(x^y)) {tr[pr].mx=tr[pr].su=nu; return; }
	RG int mid=x+y>>1;
	if(po<=mid)modify(tr[pr].ls,x,mid,po,nu);
	else modify(tr[pr].rs,mid+1,y,po,nu);
	Pu(pr);
}
int qmx(RG int pr,RG int x,RG int y,RG int u,RG int v){
	if(!pr)return 0;
	if(x==u&&y==v)return tr[pr].mx;
	RG int mid=x+y>>1;
	if(v<=mid)return qmx(tr[pr].ls,x,mid,u,v);
	if(u>mid)return qmx(tr[pr].rs,mid+1,y,u,v);
	return dmax(qmx(tr[pr].ls,x,mid,u,mid),qmx(tr[pr].rs,mid+1,y,mid+1,v));
}
int qsm(RG int pr,RG int x,RG int y,RG int u,RG int v){
	if(!pr)return 0;
	if(x==u&&y==v)return tr[pr].su;
	RG int mid=x+y>>1;
	if(v<=mid)return qsm(tr[pr].ls,x,mid,u,v);
	if(u>mid)return qsm(tr[pr].rs,mid+1,y,u,v);
	return qsm(tr[pr].ls,x,mid,u,mid)+qsm(tr[pr].rs,mid+1,y,mid+1,v);
}
inline int solvem(RG int col,RG int x,RG int f){
	int re=0;
	while(top[x]^top[f])
		re=dmax(re,qmx(root[col],1,n,lef[top[x]],lef[x])),x=fa[top[x]];
	re=dmax(re,qmx(root[col],1,n,lef[f],lef[x]));
	return re;
}
inline int solves(int col,int x,int f){
	int re=0;
	while(top[x]^top[f])
		re+=qsm(root[col],1,n,lef[top[x]],lef[x]),x=fa[top[x]];
	re+=qsm(root[col],1,n,lef[f],lef[x]);
	return re;
}
int main(){
	RG char si[10];R(n),R(q);
	for(RG int i=1;i<=n;i++)R(w[i]),R(c[i]);
	for(RG int i=1,x,y;i<n;i++)R(x),R(y),link(x,y);
	dfsi(1),dfsm(1);
	for(RG int i=1;i<=n;i++)modify(root[c[i]],1,n,lef[i],w[i]);
	for(int x,y,t,tmp;q;q--){
		scanf("%s",si),R(x),R(y);
		if(si[0]=='C'&&si[1]=='C')
			modify(root[c[x]],1,n,lef[x],0),
			c[x]=y,
			modify(root[c[x]],1,n,lef[x],w[x]);
		if(si[0]=='C'&&si[1]=='W')
			modify(root[c[x]],1,n,lef[x],y),w[x]=y;
		if(si[0]=='Q'&&si[1]=='S')
			t=lca(x,y),tmp=solves(c[x],x,t)+solves(c[x],y,t),c[x]==c[t]?tmp-=w[t]:1,printf("%d\n",tmp);
		if(si[0]=='Q'&&si[1]=='M')
			t=lca(x,y),printf("%d\n",dmax(solvem(c[x],x,t),solvem(c[x],y,t)));
	}
	return 0;
}

  

posted @ 2017-02-26 12:23  keshuqi  阅读(212)  评论(0编辑  收藏  举报