[堆][倍增]JZOJ 4811 排队
分析
先不考虑操作2,只考虑操作1
较为显然的是操作1遵从的顺序是后序遍历
而么操作2其实相当于删去这个点所在的有颜色的链的最顶端,那么会改变染色的顺序
查找链顶,我们可以用倍增,而染色的顺序如何维护?小根堆即可
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int N=1e5+10; struct Graph { int u,v,nx; friend bool operator < (Graph a,Graph b) { return a.v>b.v; } }g[2*N]; int cnt,list[N]; int s[4*N],lz[4*N],rt; int n,t,x,f[N][20],id[N],dep[N],rev[N]; bool col[N]; priority_queue<int,vector<int>,greater<int> > q; void DFS(int u,int fa) { f[u][0]=fa;dep[u]=dep[fa]+1; for (int i=list[u];i;i=g[i].nx) if (g[i].v!=fa) DFS(g[i].v,u); id[++cnt]=u;rev[u]=cnt; } int Query(int x,int l,int r,int k) { if (l==r) return l; int mid=l+r>>1; if (s[x<<1]>=k) return Query(x<<1,l,mid,k); return Query((x<<1)+1,mid+1,r,k-s[x<<1]); } int main() { scanf("%d%d",&n,&t); for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),g[++cnt]=(Graph){u,v,0},g[++cnt]=(Graph){v,u,0}; sort(g+1,g+cnt+1); cnt=0; for (int i=1;i<=2*n-2;i++) g[++cnt]=(Graph){g[i].u,g[i].v,list[g[i].u]},list[g[i].u]=cnt; cnt=0;DFS(1,0); for (int i=1;i<19;i++) for (int j=1;j<=n;j++) f[j][i]=f[f[j][i-1]][i-1]; for (int i=1;i<=n;i++) q.push(i); for (int i=1;i<=t;i++) { int op; scanf("%d%d",&op,&x); if (op==1) { int r; while (x--) col[r=id[q.top()]]=1,q.pop(); printf("%d\n",r); } else { int a=x; for (int i=18;i>=0;i--) if (col[f[a][i]]) a=f[a][i]; col[a]=0;q.push(rev[a]); printf("%d\n",dep[x]-dep[a]); } } }
在日渐沉没的世界里,我发现了你。