bzoj3133: [Baltic2013]ballmachine
我好垃圾a,这个傻逼题都不会
首先无脑把小球扔下来到达的点的顺序搞出来,这个东西其实不是很好搞。。。我是用一个链表,当前节点为根的子树中,就按孩子子树的最小值为序一个挨一个把每个孩子子树的链表连起来,当前点放最后,然后记录个头记录个尾
然后相当于在树上建立到序列的映射,扔球就是在序列找前x个变黑,在树上一个点是黑的,它的整个子树都是黑的,于是拿球可以树上倍增找第一个白点,直接改对应位置的颜色,搞个线段树维护一下,倍增logn找颜色logn所以是O(Qlog^2n)的
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #define u first #define v second #define lc now<<1 #define rc now<<1|1 #define mid (ql+qr)/2 using namespace std; typedef pair<int,int> pa; const int maxn=110000; struct node { int x,y,next; }a[maxn];int len,last[maxn]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int mn[maxn],fir[maxn],nxt[maxn],las[maxn]; /**/ int Bin[25],f[25][maxn],dep[maxn]; priority_queue< pa,vector<pa>,greater<pa> >q; /**/ //~~~~~~~~getseq&&倍增~~~~~~~~~~~~~~ void dfs(int x) { for(int i=1;Bin[i]<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]]; mn[x]=x; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; f[0][y]=x; dep[y]=dep[x]+1; dfs(y); mn[x]=min(mn[x],mn[y]); } for(int k=last[x];k;k=a[k].next)q.push(make_pair(mn[a[k].y],a[k].y)); while(!q.empty()) { int y=q.top().v;q.pop(); if(fir[x]==0)fir[x]=fir[y],las[x]=las[y]; else nxt[las[x]]=fir[y],las[x]=las[y]; } if(fir[x]==0)fir[x]=x,las[x]=x; else nxt[las[x]]=x,las[x]=x; } //---------------------------------prepare------------------------------------------------- struct trnode{int c,s,p;/*区间颜色,区间白色数量,区间最后一个白的位置*/}tr[maxn*3]; void pushdown(int now,int ql,int qr) { if(tr[now].c==0) { tr[lc].c=tr[rc].c=0; tr[lc].s=mid-ql+1,tr[rc].s=qr-mid; tr[lc].p=mid,tr[rc].p=qr; } else { tr[lc].c=tr[rc].c=1; tr[lc].s=tr[rc].s=0; tr[lc].p=tr[rc].p=-1; } } void update(int now) { if(tr[lc].c==tr[rc].c)tr[now].c=tr[lc].c; else tr[now].c=-1; tr[now].s=tr[lc].s+tr[rc].s; tr[now].p=(tr[rc].p==-1)?tr[lc].p:tr[rc].p; } void bt(int now,int ql,int qr) { tr[now].c=0;tr[now].s=qr-ql+1;tr[now].p=qr; if(ql<qr)bt(lc,ql,mid),bt(rc,mid+1,qr); } //~~~~~~~~~in~~~~~~~~~~~~~~~ void change(int now,int ql,int qr,int l,int r,int c) { if(ql==l&&qr==r) { tr[now].c=c; tr[now].s=(c==0)?qr-ql+1:0; tr[now].p=(c==0)?qr:-1; return ; } if(tr[now].c!=-1)pushdown(now,ql,qr); if(r<=mid) change(lc,ql,mid,l,r,c); else if(mid+1<=l)change(rc,mid+1,qr,l,r,c); else change(lc,ql,mid,l,mid,c),change(rc,mid+1,qr,mid+1,r,c); update(now); } bool ask(int now,int ql,int qr,int p) { if(tr[now].c!=-1)return tr[now].c; if(p<=mid)return ask(lc,ql,mid,p); else return ask(rc,mid+1,qr,p); } int cover(int now,int ql,int qr,int k) { int ret; if(tr[now].s==k){ret=tr[now].p;change(now,ql,qr,ql,qr,k);return ret;} if(tr[now].c!=-1)pushdown(now,ql,qr); if(k<tr[lc].s)ret=cover(lc,ql,mid,k); else if(tr[lc].s==k){ret=tr[lc].p;change(lc,ql,mid,ql,mid,1);} else {k-=tr[lc].s;change(lc,ql,mid,ql,mid,1);ret=cover(rc,mid+1,qr,k);} update(now); return ret; } //~~~~~~~~~~~out~~~~~~~~~~~~ //------------------------------------segtree--------------------------------------- int sa[maxn],Rank[maxn]; int main() { //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); int n,Q,x,F; scanf("%d%d",&n,&Q); len=1; for(int i=1;i<=n;i++) { scanf("%d",&F); if(F==0)x=i; else ins(F,i); } Bin[0]=1;for(int i=1;i<=24;i++)Bin[i]=Bin[i-1]*2; dfs(x); for(int i=1,k=fir[x];i<=n;i++,k=nxt[k]) sa[i]=k,Rank[k]=i; bt(1,1,n); while(Q--) { scanf("%d",&x); if(x==1) { scanf("%d",&x); printf("%d\n",sa[cover(1,1,n,x)]); } else { scanf("%d",&x); int i=0,num=0; while(i>=0) { if(Bin[i]<=dep[x]&&ask(1,1,n,Rank[f[i][x]])) x=f[i][x],num+=Bin[i],i++; else i--; } change(1,1,n,Rank[x],Rank[x],0); printf("%d\n",num); } } return 0; }
pain and happy in the cruel world.