二话不说上代码
这道题哒↓
BZOJ 1036: [ZJOI2008]树的统计Count
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,m;
const int INF=0x3f3f3f3f;
struct t1{
int to,nxt;
}edge[60057]; int cnt_edge=0;
int fst[30057];
void addedge(int x,int y){
edge[++cnt_edge].to=y;
edge[cnt_edge].nxt=fst[x];
fst[x]=cnt_edge;
}
int root;
int siz[30057],son[30057],top[30057],fth[30057];
int dpt[30057];
void dfs1(int x){
siz[x]=1;
son[x]=0;
for(int tmp=fst[x];tmp;tmp=edge[tmp].nxt){
if(edge[tmp].to==fth[x]) continue;
fth[edge[tmp].to]=x;
dpt[edge[tmp].to]=dpt[x]+1;
dfs1(edge[tmp].to);
siz[x]+=siz[edge[tmp].to];
son[x]=siz[edge[tmp].to]>siz[son[x]]?edge[tmp].to:son[x];
}
}
int dfn[30057],cnt_dfs=0;
void dfs2(int x,int tp){
top[x]=tp;
dfn[x]=++cnt_dfs;
if(son[x]) dfs2(son[x],tp);
for(int tmp=fst[x];tmp;tmp=edge[tmp].nxt){
if(edge[tmp].to==fth[x]||edge[tmp].to==son[x]) continue;
dfs2(edge[tmp].to,edge[tmp].to);
}
}
int k[30057];
struct t2{
int sum,mx;
}node[130057];
void updata(int now){
node[now].sum=node[now<<1].sum+node[now<<1|1].sum;
node[now].mx=max(node[now<<1].mx,node[now<<1|1].mx);
}
void build(int now,int l,int r){
if(l==r){
node[now].sum=node[now].mx=k[l];
// printf("%d %d: sum: %d max: %d\n",l,r,node[now].sum,node[now].mx);
return ;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
updata(now);
// printf("%d %d: sum: %d max: %d\n",l,r,node[now].sum,node[now].mx);
}
void modify(int now,int l,int r,int loc,int q){
if(l==loc&&r==loc){
node[now].sum=node[now].mx=q;
return ;
}
int mid=(l+r)>>1;
if(loc<=mid) modify(now<<1,l,mid,loc,q);
else modify(now<<1|1,mid+1,r,loc,q);
updata(now);
}
int q1(int now,int l,int r,int L,int R){
if(L<=l&&r<=R)
return node[now].mx;
int mid=(l+r)>>1;
int tp=-INF;
if(L<=mid) tp=max(tp,q1(now<<1,l,mid,L,R));
if(mid<R) tp=max(tp,q1(now<<1|1,mid+1,r,L,R));
return tp;
}
int q2(int now,int l,int r,int L,int R){
if(L<=l&&r<=R)
return node[now].sum;
int mid=(l+r)>>1;
int tp=0;
if(L<=mid) tp=q2(now<<1,l,mid,L,R);
if(mid<R) tp+=q2(now<<1|1,mid+1,r,L,R);
return tp;
}
int main(){
memset(fst,0,sizeof(fst));
memset(siz,0,sizeof(siz));
memset(son,0,sizeof(son));
memset(dpt,0,sizeof(dpt));
freopen("1.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<n;++i){
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
root=(n>>2)+1;
top[root]=root;
fth[root]=0;
dpt[0]=-1;
dfs1(root);
dfs2(root,root);
for(int i=1;i<=n;++i) scanf("%d",&k[dfn[i]]);
build(1,1,n);
scanf("%d",&m);
char tmp[10];
while(m--){
scanf("%s",tmp);
if(tmp[0]=='C'){
int a,b;
scanf("%d%d",&a,&b);
modify(1,1,n,dfn[a],b);
}
else{
int low,high;
scanf("%d%d",&low,&high);
if(dpt[top[high]]>dpt[top[low]]) swap(low,high);
if(tmp[1]=='S'){
int ans=0;
while(top[low]!=top[high]){
ans+=q2(1,1,n,dfn[top[low]],dfn[low]);
low=fth[top[low]];
if(!low) break;
if(dpt[top[low]]<dpt[top[high]]) swap(low,high);
}
if(low) ans+=q2(1,1,n,min(dfn[high],dfn[low]),max(dfn[high],dfn[low]));
printf("%d\n",ans);
}
if(tmp[1]=='M'){
int ans=-INF;
while(top[low]!=top[high]){
ans=max(ans,q1(1,1,n,dfn[top[low]],dfn[low]));
low=fth[top[low]];
if(!low) break;
if(dpt[top[low]]<dpt[top[high]]) swap(low,high);
}
if(low) ans=max(ans,q1(1,1,n,min(dfn[high],dfn[low]),max(dfn[high],dfn[low])));
printf("%d\n",ans);
}
}
}
return 0;
}

本文介绍了一种用于树形结构的动态更新与查询算法,包括边的添加、深度优先搜索、并查集构建及路径查找等核心操作。通过预处理节点信息,实现高效的查询与更新操作,适用于树状数据结构的各类应用。
729

被折叠的 条评论
为什么被折叠?



