题目
http://www.lydsy.com/JudgeOnline/problem.php?id=3531
题解
对于每一种宗教,把和这个宗教有关的点和操作单独在一棵树上搞。
查询操作很容易,修改评级也很容易,改宗教的话,就是把一个点在原来的宗教的树上赋成0,在更改后的宗教的树上加上自己的权值。
较水。。一开始数组开小了RE,改了就A了。2A。
代码
//树链剖分
//1 a b 单点赋值
//2 a b 区间和
//3 a b 区间最值
#include <cstdio>
#include <algorithm>
#define maxn 300000
#define inf 0x7fffffff
using namespace std;
int N, etot, head[maxn], to[maxn], next[maxn], totq, tid[maxn], deep[maxn], size[maxn],
fa[maxn], son[maxn], first[maxn], last[maxn], c[maxn], w[maxn], val[maxn],
top[maxn], tim;
struct quiry{int a, b, type, next, ans;}q[maxn];
struct segtree
{
int l, r, max, sum, set;
segtree *lch, *rch;
segtree(){l=r=sum=max=0;lch=rch=0;set=-1;max=-inf;}
}*root;
void adde(int a, int b){to[++etot]=b;next[etot]=head[a];head[a]=etot;}
void pushdown(segtree *p)
{
if(p->set!=-1)
{
p->sum=(p->r-p->l+1)*p->set;
p->max=p->set;
if(p->lch)p->lch->set=p->rch->set=p->set;
p->set=-1;
}
}
void update(segtree *p)
{
if(p->lch==0)return;
pushdown(p->lch),pushdown(p->rch);
p->sum=p->lch->sum+p->rch->sum;
p->max=max(p->lch->max,p->rch->max);
}
void segset(segtree *p, int l, int r, int tag)
{
pushdown(p);
int mid=(p->l+p->r)>>1;
if(l<=p->l and r>=p->r){p->set=tag;return;}
if(l<=mid)segset(p->lch,l,r,tag);
if(r>mid)segset(p->rch,l,r,tag);
update(p);
}
int segmax(segtree *p, int l, int r)
{
pushdown(p);
int mid=(p->l+p->r)>>1, ans=-inf;
if(l<=p->l and r>=p->r)return p->max;
if(l<=mid)ans=max(ans,segmax(p->lch,l,r));
if(r>mid)ans=max(ans,segmax(p->rch,l,r));
return ans;
}
int segsum(segtree *p, int l, int r)
{
pushdown(p);
int mid=(p->l+p->r)>>1, ans=0;
if(l<=p->l and r>=p->r)return p->sum;
if(l<=mid)ans+=segsum(p->lch,l,r);
if(r>mid)ans+=segsum(p->rch,l,r);
return ans;
}
void build(segtree *p, int l, int r)
{
int mid=(l+r)>>1;
p->l=l,p->r=r;
if(l==r){return;}
build(p->lch=new segtree,l,mid);
build(p->rch=new segtree,mid+1,r);
update(p);
}
void dfs1(int pos)
{
int p, v;
size[pos]=1;
for(p=head[pos];p;p=next[p])
{
if((v=to[p])==fa[pos])continue;
deep[v]=deep[pos]+1;
fa[v]=pos;
dfs1(v);
if(son[pos]==0 or size[v]>size[son[pos]])son[pos]=v;
size[pos]+=size[v];
}
}
void dfs2(int pos, int tp)
{
int p, v;
top[pos]=tp;
tid[pos]=++tim;
if(son[pos])dfs2(son[pos],tp);
for(p=head[pos];p;p=next[p])
{
if((v=to[p])==fa[pos] or v==son[pos])continue;
dfs2(v,v);
}
}
int solve(int a, int b, int type) //0:sum | 1:max
{
int ta=top[a], tb=top[b], ans=type?-inf:0, x;
while(ta!=tb)
{
if(deep[ta]<deep[tb])swap(ta,tb),swap(a,b);
if(type)x=segmax(root,tid[ta],tid[a]),ans=max(ans,x);
else x=segsum(root,tid[ta],tid[a]),ans+=x;
a=fa[ta];ta=top[a];
}
if(deep[a]>deep[b])swap(a,b);
if(type)x=segmax(root,tid[a],tid[b]),ans=max(ans,x);
else ans+=segsum(root,tid[a],tid[b]);
return ans;
}
void init()
{
int i, Q, a, b;
char s[10];
scanf("%d%d",&N,&Q);
for(i=1;i<=N;i++)
{
scanf("%d%d",&a,&b);
w[i]=a;
c[i]=b;
++totq;
if(first[b]==0)first[b]=last[b]=totq;
else q[last[b]].next=totq,last[b]=totq;
q[totq].type=1;q[totq].a=i;q[totq].b=a;
}
for(i=1;i<N;i++)scanf("%d%d",&a,&b),adde(a,b),adde(b,a);
for(i=1;i<=Q;i++)
{
scanf("%s%d%d",s,&a,&b);
++totq;
q[totq].a=a;
q[totq].b=b;
q[last[c[a]]].next=totq;
last[c[a]]=totq;
if(s[1]=='C')
{
q[totq].type=1;
q[totq].b=0;
totq++;
q[totq].type=1;
q[last[b]].next=totq;
last[b]=totq;
q[totq].a=a;q[totq].b=w[a];
c[a]=b;
}
if(s[1]=='W')q[totq].type=1,w[a]=b;
if(s[1]=='S')q[totq].type=2;
if(s[1]=='M')q[totq].type=3;
}
}
void solve(int num)
{
int pt, x, a, b;
root->set=0;
for(pt=first[num];pt;pt=q[pt].next)
{
x=q[pt].type;
a=q[pt].a;
b=q[pt].b;
if(x==1)segset(root,tid[a],tid[a],b);
if(x==2)q[pt].ans=solve(a,b,0);
if(x==3)q[pt].ans=solve(a,b,1);
}
}
void print()
{
int i;
for(i=1;i<=totq;i++)if(q[i].type!=1)printf("%d\n",q[i].ans);
}
int main()
{
int i;
init();
dfs1(1);
dfs2(1,1);
build(root=new segtree,1,tim);
for(i=1;i<=100000;i++)solve(i);
print();
return 0;
}