BZOJ 3531[Sdoi2014]旅行
BZOJ 3531[Sdoi2014]旅行
题面描述
题目分析
可以考虑到,如果这个题所有城市都只信一种宗教的话,就是一个sb树剖,直接进行链的查询和修改就能搞定。多个宗教的话,可以有一种暴力的思路对每一种宗教开线段树。但是空间不大够,考虑动态开点,把每个宗教类型当成不同的树根,然后在这个宗教的树上查询。
是代码呢
#include <bits/stdc++.h>
using namespace std;
#define mid ((l+r)>>1)
const int inf=1e9+7;
const int MAXN=1e5+7;
int size[MAXN],dep[MAXN],f[MAXN],id[MAXN],at[MAXN],top[MAXN],wson[MAXN],a[MAXN],c[MAXN],w[MAXN];
int n,m,cnt;
char s[5];
vector<int> edge[MAXN];
inline int read()
{
int x=0,c=1;
char ch=' ';
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
while(ch=='-')c*=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*c;
}
struct seg_tree{
int mx[MAXN<<5],sum[MAXN<<5],T[MAXN],L[MAXN<<5],R[MAXN<<5],size;
inline int update(int pre,int l,int r,int k,int x){
int rt=++size;
L[rt]=L[pre];R[rt]=R[pre];sum[rt]+=sum[pre]+x;mx[rt]=max(mx[pre],x);
if(l==r) return rt;
if(k<=mid) L[rt]=update(L[pre],l,mid,k,x);
else R[rt]=update(R[pre],mid+1,r,k,x);
return rt;
}
inline void del(int u,int l,int r,int k){
if(l==r){
sum[u]=mx[u]=0;
return;
}
sum[u]=mx[u]=0;
if(k<=mid) del(L[u],l,mid,k);
else del(R[u],mid+1,r,k);
sum[u]=sum[L[u]]+sum[R[u]];
mx[u]=max(mx[L[u]],mx[R[u]]);
}
inline int query_max(int dl,int dr,int l,int r,int u){
if(dl<=l&&r<=dr) return mx[u];
int lmx=-inf,rmx=-inf;
if(dl<=mid) lmx=query_max(dl,dr,l,mid,L[u]);
if(dr>mid) rmx=query_max(dl,dr,mid+1,r,R[u]);
return max(lmx,rmx);
}
inline int query_sum(int dl,int dr,int l,int r,int u){
if(dl<=l&&r<=dr) return sum[u];
int ans=0;
if(dl<=mid) ans=query_sum(dl,dr,l,mid,L[u]);
if(dr>mid) ans+=query_sum(dl,dr,mid+1,r,R[u]);
return ans;
}
}seg;
inline void dfs(int u,int fa)
{
size[u]=1,dep[u]=dep[fa]+1;f[u]=fa;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(v==fa) continue;
dfs(v,u);
size[u]+=size[v];
if(size[wson[u]]<size[v]) wson[u]=v;
}
}
inline void dfs2(int u,int tp)
{
id[u]=++cnt;w[cnt]=a[u];top[u]=tp;at[cnt]=u;
if(wson[u]) dfs2(wson[u],tp);
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(v==f[u]||v==wson[u]) continue;
dfs2(v,v);
}
}
inline int query_Max(int x,int y,int u)
{
int ans=-inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,seg.query_max(id[top[x]],id[x],1,n,u));
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans=max(ans,seg.query_max(id[x],id[y],1,n,u));
return ans;
}
inline int query_Sum(int x,int y,int u)
{
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=seg.query_sum(id[top[x]],id[x],1,n,u);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=seg.query_sum(id[x],id[y],1,n,u);
return ans;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++){
a[i]=read();c[i]=read();
}
for(int i=1;i<n;i++){
int x=read(),y=read();
edge[x].push_back(y);edge[y].push_back(x);
}
dfs(1,0);dfs2(1,1);
for(int i=1;i<=n;i++) seg.T[c[at[i]]]=seg.update(seg.T[c[at[i]]],1,n,i,a[at[i]]);
while(m--){
scanf("%s",s);
if(s[1]=='C'){
int x=read(),k=read();
seg.del(seg.T[c[x]],1,n,id[x]);
c[x]=k;
seg.T[c[x]]=seg.update(seg.T[c[x]],1,n,id[x],a[x]);
} else if(s[1]=='W') {
int x=read(),k=read();
seg.del(seg.T[c[x]],1,n,id[x]);
a[x]=k;
seg.T[c[x]]=seg.update(seg.T[c[x]],1,n,id[x],a[x]);
} else if(s[1]=='M'){
int x=read(),y=read();
int ans=query_Max(x,y,seg.T[c[x]]);
printf("%d\n", ans);
} else {
int x=read(),y=read();
int ans=query_Sum(x,y,seg.T[c[x]]);
printf("%d\n", ans);
}
}
}
对于作者转载文章,欢迎继续转载。
对于作者原创文章,请注明出处之后转载。