BZOJ1103 [POI2007]大都市meg dfs序 线段树
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1103
题意概括
一棵树上,一开始所有的边权值为1,我们要支持两种操作:
1. 修改某一条边的权值为0
2. 询问根节点到某一节点的路径权值和
题解
然后差不多你就会了。
dfs序+线段树搞定了。
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; const int N=250000+5; struct Gragh{ int cnt,x[N],y[N],nxt[N],fst[N]; void set(){ cnt=0; memset(fst,0,sizeof fst); } void add(int a,int b){ x[++cnt]=a,y[cnt]=b; nxt[cnt]=fst[a],fst[a]=cnt; } }g; int n,m,fa[N],in[N],out[N],dis[N],time; char ch[3]; struct SegTree{ int v,add; }t[N*4]; void dfs(int rt){ in[rt]=++time; for (int i=g.fst[rt];i;i=g.nxt[i]) dis[g.y[i]]=dis[rt]+1,dfs(g.y[i]); out[rt]=time; } void build(int rt,int le,int ri){ t[rt].add=t[rt].v=0; if (le==ri) return; int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1; build(ls,le,mid); build(rs,mid+1,ri); } void pushdown(int rt){ if (!t[rt].add) return; int ls=rt<<1,rs=ls|1,&v=t[rt].add; t[ls].add+=v,t[ls].v+=v; t[rs].add+=v,t[rs].v+=v; v=0; } void update(int rt,int le,int ri,int xle,int xri){ if (ri<xle||le>xri) return; if (xle<=le&&ri<=xri){ t[rt].add++,t[rt].v++; return; } pushdown(rt); int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1; update(ls,le,mid,xle,xri); update(rs,mid+1,ri,xle,xri); } int query(int rt,int le,int ri,int x){ if (le==ri) return t[rt].v; pushdown(rt); int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1; if (x<=mid) return query(ls,le,mid,x); else return query(rs,mid+1,ri,x); } int main(){ g.set(); scanf("%d",&n); for (int i=1,a,b;i<n;i++){ scanf("%d%d",&a,&b); if (a>b) swap(a,b); fa[b]=a,g.add(a,b); } time=dis[1]=0; dfs(1); build(1,1,n); scanf("%d",&m); m+=n-1; while (m--){ int x,a,b; scanf("%s",ch); if (ch[0]=='W'){ scanf("%d",&x); printf("%d\n",dis[x]-query(1,1,n,in[x])); } else { scanf("%d%d",&a,&b); if (a>b) swap(a,b); update(1,1,n,in[b],out[b]); } } return 0; }