列表

详情


NC20579. [SDOI2014]旅行

描述

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,并记下了途中留宿过 的城市的评级最大值。     
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。    
为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

输入描述

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

输出描述

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

示例1

输入:

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

输出:

8
9
11
3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 534ms, 内存消耗: 45560K, 提交时间: 2023-02-14 21:50:09

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#define ll long long
using namespace std;
const int N=100005;
ll cnt,cnt1,cnt2,dfn[N],dep[N],sz[N],ans,head[N],fa[N],hs[N],top[N],rnk[N],n,root[N],q,d[N],c[N];
struct o
{
	ll v,u;
}e[200005];
struct io
{
	ll l,r,sum,ma;
}node[30000000];
void ud(ll &rt,ll l,ll r,ll w,ll va)
{
	if(!rt) rt=++cnt2;
	ll mid=(l+r)>>1;
	if(l==r)
	{
		node[rt].sum=va;
		node[rt].ma=va;
		return;
	}
	if(w<=mid) ud(node[rt].l,l,mid,w,va);
	else ud(node[rt].r,mid+1,r,w,va);
	node[rt].sum=node[node[rt].l].sum+node[node[rt].r].sum;
	node[rt].ma=max(node[node[rt].l].ma,node[node[rt].r].ma);
}
void qus(ll l,ll r,ll l1,ll r1,ll rt)
{
	if(rt==0) return;
	if(l1>=l&&r1<=r)
	{
		ans+=node[rt].sum;
		return;
	}
	ll mid=(l1+r1)>>1;
	if(l<=mid) qus(l,r,l1,mid,node[rt].l);
	if(r>=mid+1) qus(l,r,mid+1,r1,node[rt].r);
}
void qusa(ll l,ll r,ll l1,ll r1,ll rt)
{
	if(rt==0) return;
	if(l1>=l&&r1<=r)
	{
		ans=max(ans,node[rt].ma);
		return;
	}
	ll mid=(l1+r1)>>1;
	if(l<=mid) qusa(l,r,l1,mid,node[rt].l);
	if(r>=mid+1) qusa(l,r,mid+1,r1,node[rt].r);
}
void add(ll u,ll v)
{
	cnt++;
	e[cnt].u=head[u];
	e[cnt].v=v;
	head[u]=cnt;
}
void dfs1(ll u,ll f)
{
	sz[u]=1;
	fa[u]=f;
	ll maxson=-1;
	for(ll i=head[u];i;i=e[i].u)
	{
		ll v=e[i].v;
		if(v!=f)
		{
			dep[v]=dep[u]+1;
			dfs1(v,u);
			sz[u]+=sz[v];
			if(sz[v]>maxson)
			{
				hs[u]=v;
				maxson=sz[v];
			}
		}
	}
}
void dfs2(ll u,ll t)
{
	top[u]=t;
	cnt1++;
	dfn[u]=cnt1;
	rnk[dfn[u]]=u;
	rnk[cnt1]=u;
	if(hs[u]==0) return;
	dfs2(hs[u],t);
	for(ll i=head[u];i;i=e[i].u)
	{
		ll v=e[i].v;
		if(v!=fa[u]&&v!=hs[u])
		{
			dfs2(v,v);
		}
	}
}
void op1(ll u,ll v,ll val)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		qus(dfn[top[u]],dfn[u],1,n,root[val]);
		u=fa[top[u]];
	}
	if(dfn[u]>dfn[v]) qus(dfn[v],dfn[u],1,n,root[val]);
	else qus(dfn[u],dfn[v],1,n,root[val]);
}
void op2(ll u,ll v,ll val)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		qusa(dfn[top[u]],dfn[u],1,n,root[val]);
		u=fa[top[u]];
	}
	if(dfn[u]>dfn[v]) qusa(dfn[v],dfn[u],1,n,root[val]);
	else qusa(dfn[u],dfn[v],1,n,root[val]);
}
int main()
{
	cin>>n>>q;
	for(ll i=1;i<=n;i++)
	{
		cin>>d[i]>>c[i];
	}
	for(ll i=1;i<n;i++)
	{
		ll x,y;
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	dfs1(1,0);
	dfs2(1,1);
	for(ll i=1;i<=n;i++)
	{
		ud(root[c[i]],1,n,dfn[i],d[i]);
	}
	char zf[3];
	for(ll i=1;i<=q;i++)
	{
		ll x,y;
		cin>>zf>>x>>y;
		if(zf[1]=='C')
		{
			ud(root[c[x]],1,n,dfn[x],0);
			c[x]=y;
			ud(root[y],1,n,dfn[x],d[x]);
		}
		if(zf[1]=='W')
		{
			d[x]=y;
			ud(root[c[x]],1,n,dfn[x],y);
		}
		if(zf[1]=='S')
		{
			ans=0;
			op1(x,y,c[x]);
			cout<<ans<<'\n';
		}
		if(zf[1]=='M')
		{
			ans=0;
			op2(x,y,c[x]);
			cout<<ans<<'\n';
		}
	}
	return 0;
}

C++ 解法, 执行用时: 597ms, 内存消耗: 26312K, 提交时间: 2022-06-26 18:13:02

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 1;
struct node{
	int l,r,sum,max;
}tree[maxn << 4];
struct edge{
	int to,next;
}e[maxn << 1]; 
int head[maxn],cnt,w[maxn],c[maxn],Size[maxn],son[maxn],f[maxn],d[maxn];
int top[maxn],id[maxn],rk[maxn],root[maxn],x,y,qsum,qmax;
void add(const int &a,const int &b){
	cnt++;
	e[cnt].to = b;
	e[cnt].next = head[a];
	head[a] = cnt;
}
void dfs1(const int &u){
	d[u] = d[f[u]] + 1;
	Size[u] = 1;
	for (int i = head[u];i;i = e[i].next){
		int &v = e[i].to;
		if (v != f[u]){
			f[v] = u;
			dfs1(v);
			Size[u] += Size[v];
			if (Size[v] > Size[son[u]])
				son[u] = v;
		}
	}
}
void dfs2(const int &u){
	id[u] = ++id[0];
	rk[id[0]] = u;
	if (!son[u])return;
	top[son[u]] = top[u];
	dfs2(son[u]);
	for (int i = head[u];i;i = e[i].next){
		int &v = e[i].to;
		if (!top[v]){
			top[v] = v;
			dfs2(v);
		}
	}
}
void push(const int &k){
	tree[k].sum = tree[tree[k].l].sum + tree[tree[k].r].sum;
	tree[k].max = max(tree[tree[k].l].max,tree[tree[k].r].max);
}
void C(int &k,int l,int r,const int &pos){
	if (!k)k = ++cnt;
	if (l == r){
		tree[k].sum = tree[k].max = w[rk[pos]];
		return;
	}
	int mid = l + r >> 1;
	if (pos <= mid)
		C(tree[k].l,l,mid,pos);
	else C(tree[k].r,mid + 1,r,pos);
	push(k);
}
void del(const int &k,int l,int r){
	if (l == r){
		tree[k].sum = tree[k].max = 0;
		return;
	}
	int mid = l + r >> 1;
	if (id[x] <= mid)
		del(tree[k].l,l,mid);
	else del(tree[k].r,mid + 1,r);
	push(k);
}
void Q(const int &k,int l,int r,const int &a,const int &b){
	if (a <= l && r <= b){
		qsum += tree[k].sum;
		qmax = max(qmax,tree[k].max);
		return;
	}else if(l == r)
		return;
	int mid = l + r >> 1;
	if (a <= mid)
		Q(tree[k].l,l,mid,a,b);
	if (b > mid)
		Q(tree[k].r,mid + 1,r,a,b);
}
int main(){
	int n,q,i;
	cin>>n>>q;
	for (i = 1;i <= n;i++)
		cin>>w[i]>>c[i];
	for (i = 1;i < n;i++){
		cin>>x>>y;
		add(x,y);
		add(y,x);
	}
	dfs1(1);
	top[1] = 1;
	dfs2(1);
	cnt = 0;
	for (i = 1;i <= n;i++)
		C(root[c[i]],1,n,id[i]);
	char op[3];
	while (q--){
		cin>>op>>x>>y;
		if (op[0] == 'C'){
			del(root[c[x]],1,n);
			if (op[1] == 'C')
				c[x] = y;
			else w[x] = y;
			C(root[c[x]],1,n,id[x]);
		}else{
			i = c[x];
			qsum = qmax = 0;
			while (top[x] != top[y]){
				if (d[top[x]] < d[top[y]])
					swap(x,y);
				Q(root[i],1,n,id[top[x]],id[x]);
				x = f[top[x]];
			} 
			if (d[x] > d[y])
				swap(x,y);
			Q(root[i],1,n,id[x],id[y]);
			cout<<(op[1] == 'S' ? qsum : qmax)<<endl;
		}
	}
	return 0;
}

上一题