洛谷 P3038 [USACO11DEC]牧草种植Grass Planting(树链剖分)
题解:仍然是无脑树剖,要注意一下边权,然而这种没有初始边权的题目其实和点权也没什么区别了
代码如下:
#include<cstdio> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #define lson root<<1 #define rson root<<1|1 using namespace std; struct node { int lazy,sum,l,r; } tr[400040]; int deep[100010],fa[100010],son[100010],size[100010],id[100010],top[100010],cnt; vector<int> g[100010]; void push_up(int root) { tr[root].sum=tr[lson].sum+tr[rson].sum; } void push_down(int root) { int mid=(tr[root].l+tr[root].r)>>1; tr[lson].sum+=tr[root].lazy*(mid-tr[root].l+1); tr[lson].lazy+=tr[root].lazy; tr[rson].sum+=tr[root].lazy*(tr[root].r-mid); tr[rson].lazy+=tr[root].lazy; tr[root].lazy=0; } void build(int root,int l,int r) { if(l==r) { tr[root].l=l; tr[root].r=r; tr[root].sum=0; return ; } tr[root].l=l; tr[root].r=r; int mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); push_up(root); } void update(int root,int l,int r,int val) { if(l>r) { return; } if(l==tr[root].l&&tr[root].r==r) { tr[root].sum+=val*(tr[root].r-tr[root].l+1); tr[root].lazy+=val; return ; } if(tr[root].lazy) { push_down(root); } int mid=(tr[root].l+tr[root].r)>>1; if(l>mid) { update(rson,l,r,val); } else { if(r<=mid) { update(lson,l,r,val); } else { update(lson,l,mid,val); update(rson,mid+1,r,val); } } push_up(root); } int query(int root,int l,int r) { if(l>r) { return 0; } if(l==tr[root].l&&r==tr[root].r) { return tr[root].sum; } if(tr[root].lazy) { push_down(root); } int mid=(tr[root].l+tr[root].r)>>1; if(l>mid) { return query(rson,l,r); } else { if(r<=mid) { return query(lson,l,r); } } return query(lson,l,mid)+query(rson,mid+1,r); } void dfs1(int now,int f,int dep) { deep[now]=dep; fa[now]=f; size[now]=1; int maxson=-1; for(int i=0; i<g[now].size(); i++) { if(g[now][i]==f) { continue; } dfs1(g[now][i],now,dep+1); size[now]+=size[g[now][i]]; if(size[g[now][i]]>maxson) { son[now]=g[now][i]; maxson=size[g[now][i]]; } } } void dfs2(int now,int topf) { id[now]=++cnt; top[now]=topf; if(!son[now]) { return ; } dfs2(son[now],topf); for(int i=0; i<g[now].size(); i++) { if(fa[now]==g[now][i]||son[now]==g[now][i]) { continue; } dfs2(g[now][i],g[now][i]); } } void path_update(int x,int y,int val) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) { swap(x,y); } update(1,id[top[x]],id[x],val); x=fa[top[x]]; } if(deep[x]>deep[y]) { swap(x,y); } update(1,id[x]+1,id[y],val); } int path_query(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) { swap(x,y); } ans+=query(1,id[top[x]],id[x]); x=fa[top[x]]; } if(deep[x]>deep[y]) { swap(x,y); } ans+=query(1,id[x]+1,id[y]); return ans; } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1; i<=n-1; i++) { int from,to; scanf("%d%d",&from,&to); g[from].push_back(to); g[to].push_back(from); } dfs1(1,0,1); dfs2(1,1); build(1,1,n); for(int i=1; i<=m; i++) { int from,to; char kd; scanf("\n%c %d %d",&kd,&from,&to); if(kd=='P') { path_update(from,to,1); } if(kd=='Q') { printf("%d\n",path_query(from,to)); } } }