洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线
Code:
#include <map> #include <cstdio> #include <algorithm> #include <cstring> #include <string> using namespace std; void setIO(string a){ freopen((a+".in").c_str(),"r",stdin); freopen((a+".out").c_str(),"w",stdout); } #define N 30005 #define Q 40005 #define M 100005 int n,m,cnt=1; int head[N]; int to[M<<1]; int nex[M<<1]; int siz[N]; int f[N]; int son[N]; int dep[N]; int uu[M<<1]; int vv[M<<1]; bool tag[M<<1]; bool vis[N]; void addedge(int u,int v){ nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v; uu[cnt]=u,vv[cnt]=v; } void dfs1(int u,int fa,int depth){ siz[u]=1,f[u]=fa,vis[u]=1,dep[u]=depth+1; for(int v=head[u];v;v=nex[v]){ if(!vis[to[v]]&&to[v]!=fa) { tag[v]=tag[v^1]=1; dfs1(to[v],u,depth+1); siz[u]+=siz[to[v]]; if(siz[to[v]]>siz[son[u]]) son[u]=to[v]; } } } int A[N]; int top[N]; int cnt2=0; void dfs2(int u,int tp){ top[u]=tp; A[u]=++cnt2; if(son[u])dfs2(son[u],tp); for(int v=head[u];v;v=nex[v]) if(to[v]!=son[u]&&to[v]!=f[u]&&tag[v])dfs2(to[v],to[v]); //if(!son[u]) son[u]=u; } int sumv[N<<2]; int lazy[N<<2]; #define lson (o<<1) #define rson (o<<1)|1 void pushup(int o){ sumv[o]=sumv[lson]+sumv[rson]; if(lazy[lson]&&lazy[rson]) lazy[o]=1,sumv[o]=0; } void build(int l,int r,int o){ if(l>r)return; if(l==r) { sumv[o]=1; if(l==1)sumv[o]=0; return; } int mid=(l+r)>>1; build(l,mid,lson); build(mid+1,r,rson); pushup(o); } void modify(int l,int r,int o,int L,int R){ if(l>r||r<L||l>R)return; if(lazy[o])return; if(l>=L&&r<=R){ sumv[o]=0; lazy[o]=1; return; } int mid=(l+r)>>1; modify(l,mid,lson,L,R); modify(mid+1,r,rson,L,R); pushup(o); } int query(int l,int r,int o,int L,int R){ if(lazy[o]||l>r||r<L||l>R)return 0; if(l>=L&&r<=R)return sumv[o]; int mid=(l+r)>>1; return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R); } void update(int a,int b){ while(top[a]!=top[b]){ if(dep[top[a]]>dep[top[b]]) swap(a,b); modify(1,n,1,A[top[b]],A[b]),b=f[top[b]]; } if(a==b)return ; if(dep[a]>dep[b]) swap(a,b); modify(1,n,1,A[son[a]],A[b]); } int lookup(int a,int b){ int sums=0; while(top[a]!=top[b]){ if(dep[top[a]]>dep[top[b]]) swap(a,b); sums+=query(1,n,1,A[top[b]],A[b]); b=f[top[b]]; } if(a==b) return sums; if(dep[a]>dep[b])swap(a,b); sums+=query(1,n,1,A[son[a]],A[b]); return sums; } struct Edge{ int from,to,t; Edge(int from=0,int to=0,int t=0):from(from),to(to),t(t){} }edges[M]; struct Ask{ int a,b,c; Ask(int a=0,int b=0,int c=0):a(a),b(b),c(c){} }asks[Q]; typedef pair<int,int> P; map<P,int>idx; int curr; int answer[Q]; int cnans; int main(){ //setIO("input"); scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ int a,b; scanf("%d%d",&a,&b); if(a>b)swap(a,b); edges[i]=Edge(a,b,0); idx[P(a,b)]=i; } while(1){ int a,b,c; scanf("%d%d%d",&c,&b,&a); if(c==-1) break; if(a>b)swap(a,b); asks[++curr]=Ask(a,b,c); if(c!=1&&idx[P(a,b)]) edges[idx[P(a,b)]].t=1; } for(int i=1;i<=m;++i) if(edges[i].t!=1) addedge(edges[i].from,edges[i].to),addedge(edges[i].to,edges[i].from); dfs1(1,0,0); dfs2(1,1); build(1,n,1); for(int i=2;i<=cnt;i+=2) if(!tag[i]){ tag[i]=tag[i^1]=1; update(uu[i],vv[i]); } for(int i=curr;i>=1;--i) { if(asks[i].c==1) answer[++cnans]=lookup(asks[i].a,asks[i].b); else update(asks[i].a,asks[i].b); } for(int i=cnans;i>=1;--i) printf("%d\n",answer[i]); return 0; }