您的位置:首页 > 其它

BZOJ 3531: [Sdoi2014]旅行

2014-05-14 11:43 281 查看
题目地址:http :// www . lydsy . com / JudgeOnline / problem . php ? id = 3531

题目大意:见原题。

算法讨论:树链剖分。对于每种宗教开一棵线段树即可。

Code:

#include <cstdio>
#include <algorithm>

#define N 3000000
#define M 30000000
#define oo 0x7f7f7f7f

using namespace std;

int n,q,x,y,mm,tot,digit[10],w[N+10],c[N+10],next[N+10],son[N+10],ed[N+10],fa[N+10],head[N+10],heavy[N+10],
size[N+10],deep[N+10],id[N+10],tree1[M+10],tree2[M+10],l[N+10],r[N+10],root[N+10];
bool vis[N+10];
char s[10];

void add(int x,int y){
next[++mm]=son[x];
son[x]=mm;
ed[mm]=y;
}

void dfs1(int x){
vis[x]=1;
size[x]=1;
for (int i=son[x];i;i=next[i]){
int y=ed[i];
if (!vis[y]){
fa[y]=x;
deep[y]=deep[x]+1;
dfs1(y);
size[x]+=size[y];
if (size[y]>size[heavy[x]]) heavy[x]=y;
}
}
}

void dfs2(int x){
vis[x]=1;
id[x]=++tot;
if (!head[x]) head[x]=x;
if (heavy[x]){
head[heavy[x]]=head[x];
dfs2(heavy[x]);
}
for (int i=son[x];i;i=next[i]){
int y=ed[i];
if (!vis[y]) dfs2(y);
}
}

void up(int rt){
tree1[rt]=tree1[l[rt]]+tree1[r[rt]];
tree2[rt]=max(tree2[l[rt]],tree2[r[rt]]);
}

void modify(int& rt,int lc,int rc,int x,int y){
if (!rt) rt=++tot;
if (lc==rc){
tree1[rt]=y;
tree2[rt]=y;
return;
}
int mid=(lc+rc)/2;
if (x<=mid) modify(l[rt],lc,mid,x,y);
else modify(r[rt],mid+1,rc,x,y);
up(rt);
}

int qsum(int rt,int lc,int rc,int L,int R){
if (!rt) return 0;
if (L==lc && R==rc) return tree1[rt];
int mid=(lc+rc)/2;
if (R<=mid) return qsum(l[rt],lc,mid,L,R);
if (L>mid) return qsum(r[rt],mid+1,rc,L,R);
return qsum(l[rt],lc,mid,L,mid)+qsum(r[rt],mid+1,rc,mid+1,R);
}

int qmax(int rt,int lc,int rc,int L,int R){
if (!rt) return 0;
if (L==lc && R==rc) return tree2[rt];
int mid=(lc+rc)/2;
if (R<=mid) return qmax(l[rt],lc,mid,L,R);
if (L>mid) return qmax(r[rt],mid+1,rc,L,R);
return max(qmax(l[rt],lc,mid,L,mid),qmax(r[rt],mid+1,rc,mid+1,R));
}

int qs(int x,int y){
int ans=0,C=c[x];
while (head[x]!=head[y]){
if (deep[head[x]]<deep[head[y]]) swap(x,y);
ans+=qsum(root[C],1,n,id[head[x]],id[x]);
x=fa[head[x]];
}
if (deep[x]>deep[y]) swap(x,y);
ans+=qsum(root[C],1,n,id[x],id[y]);
return ans;
}

int qm(int x,int y){
int ans=-oo,C=c[x];
while (head[x]!=head[y]){
if (deep[head[x]]<deep[head[y]]) swap(x,y);
ans=max(ans,qmax(root[C],1,n,id[head[x]],id[x]));
x=fa[head[x]];
}
if (deep[x]>deep[y]) swap(x,y);
ans=max(ans,qmax(root[C],1,n,id[x],id[y]));
return ans;
}

int main(){
#ifndef ONLINE_JUDGE
freopen("3531.in","r",stdin);
freopen("3531.out","w",stdout);
#endif
scanf("%d%d",&n,&q);
for (int i=1;i<=n;++i) scanf("%d%d",&w[i],&c[i]);
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(1);
for (int i=1;i<=n;++i) vis[i]=0;
dfs2(1);
tot=0;
for (int i=1;i<=n;++i) modify(root[c[i]],1,n,id[i],w[i]);
for (int i=1;i<=q;++i){
scanf("%s%d%d",s,&x,&y);
if (s[0]=='C')
if (s[1]=='C'){
modify(root[c[x]],1,n,id[x],0);
modify(root[y],1,n,id[x],w[x]);
c[x]=y;
}
else{
modify(root[c[x]],1,n,id[x],y);
w[x]=y;
}
else if (s[1]=='S') printf("%d\n",qs(x,y));
else printf("%d\n",qm(x,y));
}
return 0;
}

By Charlie Pan
Mar 14,2014


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  BZOJ SDOI 树链剖分