题
bzoj3924YES
bzoj4034YES
bzoj1576YES
bzoj3626YES神转化
bzoj2325
bzoj3589
bzoj4538
bzoj2908
bzoj3694YES
bzoj1146二分+树链剖分+线段树套平衡树
bzoj3531YES
bzoj1984YES
bzoj2243YES
bzoj4196YES
bzoj1036YES
poj3237YES
//bzoj3531
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=131072;
const int inf=21333333;
int dep[N],sz[N],top[N],fa[N],pos[N],h[N];
int mx[N*100],sum[N*100],root[N*100],ls[N*100],rs[N*100];
int n,m,tot,x,y,z,w[N],c[N],tm,size;
struct edge{int y,next;}g[N*2];
char s[10];
void adp(int x,int y){
g[++tot].y=y;
g[tot].next=h[x];
h[x]=tot;
}
void dfs1(int x){
sz[x]=1;
for (int i=h[x];i;i=g[i].next)
if (g[i].y!=fa[x]){
fa[g[i].y]=x;
dep[g[i].y]=dep[x]+1;
dfs1(g[i].y);
sz[x]+=sz[g[i].y];
}
}
void dfs2(int x,int t){
top[x]=t;pos[x]=++tm;
int son=0;
for (int i=h[x];i;i=g[i].next)
if (g[i].y!=fa[x] && sz[son]<sz[g[i].y])
son=g[i].y;
if (son) dfs2(son,t);
for (int i=h[x];i;i=g[i].next)
if (g[i].y!=fa[x] && g[i].y!=son)
dfs2(g[i].y,g[i].y);
}
int lca(int x,int y){
while (top[x]!=top[y]){
if (dep[top[x]]>dep[top[y]])
x=fa[top[x]]; else
y=fa[top[y]];
}
if (dep[x]<dep[y])
return x;
return y;
}
void pushup(int rt){
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
mx[rt]=max(mx[ls[rt]],mx[rs[rt]]);
}
void change(int &rt,int l,int r,int k,int val){
if (!rt) rt=++size;
if (l==r){mx[rt]=sum[rt]=val;return;}
int mid=(l+r)>>1;
if (k<=mid)
change(ls[rt],l,mid,k,val); else
change(rs[rt],mid+1,r,k,val);
pushup(rt);
}
int querymax(int rt,int l,int r,int ll,int rr){
if (!rt) return 0;
if (l==ll && rr==r) return mx[rt];
int mid=(l+r)>>1;int res=-inf;
if (ll<=mid) res=max(res,querymax(ls[rt],l,mid,ll,min(mid,rr)));
if (rr> mid) res=max(res,querymax(rs[rt],mid+1,r,max(mid+1,ll),rr));
return res;
}
int querysum(int rt,int l,int r,int ll,int rr){
if (!rt) return 0;
if (l==ll && rr==r) return sum[rt];
int mid=(l+r)>>1;int res=0;
if (ll<=mid) res+=querysum(ls[rt],l,mid,ll,min(mid,rr));
if (rr> mid) res+=querysum(rs[rt],mid+1,r,max(mid+1,ll),rr);
return res;
}
int querysum(int cc,int x,int f){
int res=0;
while (top[x]!=top[f]){
res+=querysum(root[cc],1,n,pos[top[x]],pos[x]);
x=fa[top[x]];
}
res+=querysum(root[cc],1,n,pos[f],pos[x]);
return res;
}
int querymax(int cc,int x,int f){
int res=-inf;
while (top[x]!=top[f]){
res=max(res,querymax(root[cc],1,n,pos[top[x]],pos[x]));
x=fa[top[x]];
}
res=max(res,querymax(root[cc],1,n,pos[f],pos[x]));
return res;
}
int main(){
scanf("%d%d",&n,&m);
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);
adp(x,y);adp(y,x);
}
dfs1(1);dfs2(1,1);
for (int i=1;i<=n;i++)
change(root[c[i]],1,n,pos[i],w[i]);
while (m--){
scanf("%s",s);
if (s[0]=='Q'){
scanf("%d%d",&x,&y);
int f=lca(x,y);
if (s[1]=='S')
printf("%d\n",querysum(c[x],x,f)+querysum(c[x],y,f)-(c[x]==c[f])*w[f]); else
printf("%d\n",max(querymax(c[x],x,f),querymax(c[x],y,f)));
} else {
scanf("%d%d",&x,&z);
if (s[1]=='C'){
change(root[c[x]],1,n,pos[x],0);
c[x]=z;
change(root[c[x]],1,n,pos[x],w[x]);
} else change(root[c[x]],1,n,pos[x],z),w[x]=z;
}
}
}
应用
将树上路径转化为序列用线段树维护。
将某棵子树(dfs序)询问转化为序列用线段树维护。
支持单点修改,路径修改,子树修改。
支持路径求和….
注意:树的形态不能变。