[SDOI2014]旅行(树链剖分+动态开点线段树)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/C20180602_csq/article/details/100837297

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。

题解

对每一种宗教都开一棵线段树直接统计

由于空间会爆,所以我们选择动态开点(多写几次就熟了,有点像主席树)

这样空间大约在nlogn左右,就可以做了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{
	char c;int num=0,flg=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
	while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
	return num*flg;
}
int n,Q;
#define N 100005
int fir[N],to[2*N],nxt[2*N],cnt;
void adde(int a,int b)
{
	to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;
	to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;
}
int dep[N],fa[N],top[N],siz[N],son[N];
int pos[N],dfn;
void dfs1(int u,int deep)
{
	dep[u]=deep;siz[u]=1;
	int v,p;
	for(p=fir[u];p;p=nxt[p]){
		v=to[p];
		if(v!=fa[u]){
			fa[v]=u;
			dfs1(v,deep+1);
			siz[u]+=siz[v];
			if(siz[son[u]]<siz[v])
				son[u]=v;
		}
	}
}
void dfs2(int u)
{
	pos[u]=(++dfn);
	if(son[u]) top[son[u]]=top[u],dfs2(son[u]);
	int v,p;
	for(p=fir[u];p;p=nxt[p]){
		v=to[p];
		if(v!=fa[u]&&v!=son[u])
			top[v]=v,dfs2(v);
	}
}
#define LL long long
struct node{
	int l,r,mx;
	LL sum;
}a[N*19];
int T[N],tot;
void pushup(int i)
{
	a[i].sum=1ll*a[a[i].l].sum+1ll*a[a[i].r].sum;
	a[i].mx=max(a[a[i].l].mx,a[a[i].r].mx);
}
int insert(int i,int l,int r,int x,int k)
{
	int nrt=i;
	if(!nrt)nrt=(++tot);
	if(l==r){
		a[nrt].mx=a[nrt].sum=k;
		return nrt;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
		a[nrt].l=insert(a[nrt].l,l,mid,x,k);
	else
		a[nrt].r=insert(a[nrt].r,mid+1,r,x,k);
	pushup(nrt);
	return nrt;
}
LL querysum(int i,int l,int r,int ql,int qr)
{
	if(!i||l>qr||r<ql) return 0ll;
	if(ql<=l&&r<=qr)
		return 1ll*a[i].sum;
	int mid=(l+r)>>1;
	return 1ll*querysum(a[i].l,l,mid,ql,qr)+1ll*querysum(a[i].r,mid+1,r,ql,qr);
}
int querymax(int i,int l,int r,int ql,int qr)
{
	if(!i||l>qr||r<ql) return 0;
	if(ql<=l&&r<=qr)
		return a[i].mx;
	int mid=(l+r)>>1;
	return max(querymax(a[i].l,l,mid,ql,qr),querymax(a[i].r,mid+1,r,ql,qr));
}
LL QPsum(int c,int x,int y)
{
	LL ret=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		ret+=querysum(T[c],1,n,pos[top[x]],pos[x]);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	ret+=querysum(T[c],1,n,pos[x],pos[y]);
	return ret;
}
int QPmax(int c,int x,int y)
{
	int ret=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		ret=max(ret,querymax(T[c],1,n,pos[top[x]],pos[x]));
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	ret=max(ret,querymax(T[c],1,n,pos[x],pos[y]));
	return ret;
}
int C[N],W[N];
char ch[4];
int main()
{
	int i,u,v;
	n=gi();Q=gi();
	for(i=1;i<=n;i++)
		W[i]=gi(),C[i]=gi();
	for(i=1;i<n;i++){
		u=gi();v=gi();
		adde(u,v);
	}
	dfs1(1,0);top[1]=1;dfs2(1);
	for(i=1;i<=n;i++)
		T[C[i]]=insert(T[C[i]],1,n,pos[i],W[i]);
	for(i=1;i<=Q;i++){
		scanf("%s",ch);
		u=gi();v=gi();
		if(ch[0]=='C'){
			if(ch[1]=='C'){
				T[C[u]]=insert(T[C[u]],1,n,pos[u],0);
				T[v]=insert(T[v],1,n,pos[u],W[u]);
				C[u]=v;
			}
			else{
				T[C[u]]=insert(T[C[u]],1,n,pos[u],v);
				W[u]=v;
			}
		}
		if(ch[0]=='Q'){
			if(ch[1]=='S')
				printf("%lld\n",QPsum(C[u],u,v));
			else
				printf("%d\n",QPmax(C[u],u,v));
		}
	}
}

居然1A了!

猜你喜欢

转载自blog.csdn.net/C20180602_csq/article/details/100837297