BZOJ 3631: [JLOI2014]松鼠的新家
从出发点开始依次修改路径上的点权值,然后就是+1或-1的问题。
#include<complex> #include<cstdio> using namespace std; const int N=3e5+7; struct node{ int v,nxt; }e[N<<1]; int n,Enum,tim; int front[N],a[N],tree[N<<2],lazy[N<<2]; int fat[N],son[N],siz[N],tid[N],top[N],dep[N]; int qread() { int x=0; char ch=getchar(); while(ch<'0' || ch>'9')ch=getchar(); while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } void Insert(int u,int v) { e[++Enum].v=v; e[Enum].nxt=front[u]; front[u]=Enum; } void dfs1(int x) { siz[x]=1; for(int i=front[x];i;i=e[i].nxt) { int v=e[i].v; if(v==fat[x])continue; fat[v]=x; dep[v]=dep[x]+1; dfs1(v); siz[x]+=siz[v]; if(siz[v]>siz[son[x]]) son[x]=v; } } void dfs2(int x,int tp) { top[x]=tp; tid[x]=++tim; if(!son[x])return; dfs2(son[x],tp); for(int i=front[x];i;i=e[i].nxt) if(e[i].v!=son[x] && e[i].v!=fat[x]) dfs2(e[i].v,e[i].v); } void PushDown(int rt) { if(lazy[rt]) { tree[rt<<1]+=lazy[rt]; tree[rt<<1|1]+=lazy[rt]; lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } } void Modify(int l,int r,int rt,int nowl,int nowr,int v) { if(nowl<=l && r<=nowr) { tree[rt]+=v; lazy[rt]+=v; return; } PushDown(rt); int mid=l+r>>1; if(nowl<=mid)Modify(l,mid,rt<<1,nowl,nowr,v); if(mid<nowr)Modify(mid+1,r,rt<<1|1,nowl,nowr,v); } int Query(int l,int r,int rt,int p) { if(l==r)return tree[rt]; PushDown(rt); int mid=l+r>>1; if(p<=mid)return Query(l,mid,rt<<1,p); else return Query(mid+1,r,rt<<1|1,p); } void ModifyRoad(int x,int y) { int f1=top[x],f2=top[y]; while(f1!=f2) { if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y); Modify(1,n,1,tid[f1],tid[x],1); x=fat[f1];f1=top[x]; } if(dep[x]>dep[y])swap(x,y); Modify(1,n,1,tid[x],tid[y],1); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) a[i]=qread(); int u,v; for(int i=1;i<n;i++) { u=qread();v=qread(); Insert(u,v); Insert(v,u); } dfs1(1);dfs2(1,1); int now=a[1]; for(int i=2;i<=n;i++) { ModifyRoad(now,a[i]); now=a[i]; Modify(1,n,1,tid[now],tid[now],-1); } for(int i=1;i<=n;i++) printf("%d\n",Query(1,n,1,tid[i])); return 0; }
另附一种树上差分的做法
#include<complex> #include<cstdio> using namespace std; const int N=3e5+7; struct node{ int v,nxt; }e[N<<1]; int n,Enum; int front[N],cnt[N],a[N]; int fat[N],son[N],top[N],siz[N],dep[N]; int qread() { int x=0; char ch=getchar(); while(ch<'0' || ch>'9')ch=getchar(); while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } void Insert(int u,int v) { e[++Enum].v=v; e[Enum].nxt=front[u]; front[u]=Enum; } void dfs1(int x) { siz[x]=1; for(int i=front[x];i;i=e[i].nxt) { int v=e[i].v; if(v==fat[x])continue; fat[v]=x; dep[v]=dep[x]+1; dfs1(v); siz[x]+=siz[v]; if(siz[v]>siz[son[x]]) son[x]=v; } } void dfs2(int x,int tp) { top[x]=tp; if(!son[x])return; dfs2(son[x],tp); for(int i=front[x];i;i=e[i].nxt) if(e[i].v!=son[x] && e[i].v!=fat[x]) dfs2(e[i].v,e[i].v); } int Lca(int x,int y) { int f1=top[x],f2=top[y]; while(f1!=f2) { if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y); x=fat[f1];f1=top[x]; } if(dep[x]<dep[y])return x; return y; } void dfs3(int x) { for(int i=front[x];i;i=e[i].nxt) if(e[i].v!=fat[x]) { dfs3(e[i].v); cnt[x]+=cnt[e[i].v]; } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) a[i]=qread(); int u,v; for(int i=1;i<n;i++) { u=qread();v=qread(); Insert(u,v); Insert(v,u); } dfs1(1);dfs2(1,1); int lca; for(int i=1;i<n;i++) { lca=Lca(a[i],a[i+1]); cnt[a[i]]++;cnt[a[i+1]]++; cnt[lca]--;cnt[fat[lca]]--; } dfs3(1); for(int i=2;i<=n;i++) cnt[a[i]]--; for(int i=1;i<=n;i++) printf("%d\n",cnt[i]); return 0; }