bzoj3731: Gty的超级妹子树
一代神题啊orz(至少是以前年代的神题吧)
块状树
复杂度nsqrtnlogn
真是exciting
还没有卡时限
话不多说直接上代码
(最近解锁了记事本写代码的技能...感觉越来越依赖OJ调试了...啊感觉写代码准确率高了不少qwq)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <algorithm> #include <vector> #define N 200006 #define M 400006 using namespace std; inline int read(){ int ret=0;char ch=getchar(); while (ch<'0'||ch>'9') ch=getchar(); while ('0'<=ch&&ch<='9'){ ret=ret*10-48+ch; ch=getchar(); } return ret; } const int KK=400; vector<int> seq[N]; struct edge{ int adj,next; edge(){} edge(int _adj,int _next):adj(_adj),next(_next){} } e[M]; int n,g[N],m; void AddEdge(int u,int v){ e[++m]=edge(v,g[u]);g[u]=m; e[++m]=edge(u,g[v]);g[v]=m; } int w[N]; vector<int> nxt[N]; int fa[N],bl[N],sz[N],cnt,top[N]; void refresh(int u,int p){ for (;p>0&&seq[u][p]<seq[u][p-1];--p)swap(seq[u][p],seq[u][p-1]); for (;p<sz[u]-1&&seq[u][p]>seq[u][p+1];++p)swap(seq[u][p],seq[u][p+1]); } void newnode(int u){ if (sz[bl[fa[u]]]==KK){ sz[bl[u]=++cnt]=0; top[cnt]=u; } else bl[u]=bl[fa[u]]; ++sz[bl[u]]; } void dfs(int u){ newnode(u); for (int i=g[u];i;i=e[i].next){ int v=e[i].adj; if (v==fa[u]) continue; fa[v]=u; dfs(v); } } void dfs_pre(int u){ seq[bl[u]].push_back(w[u]);++sz[bl[u]]; for (int i=g[u];i;i=e[i].next)if (fa[e[i].adj]==u){ int v=e[i].adj; if (bl[v]==bl[u]) dfs_pre(v); else nxt[bl[u]].push_back(bl[v]); } } void prepare(int id){ seq[id].clear();vector<int>(seq[id]).swap(seq[id]); nxt[id].clear();vector<int>(nxt[id]).swap(nxt[id]); sz[id]=0; dfs_pre(top[id]); sort(seq[id].begin(),seq[id].end()); } int solve(int u,int lmt){ int l=-1,r=sz[u],mid; while (l+1<r){ mid=l+r>>1; if (seq[u][mid]<=lmt) l=mid; else r=mid; } int ret=sz[u]-l-1; for (int j=nxt[u].size()-1;j>=0;--j) ret+=solve(nxt[u][j],lmt); return ret; } int query(int u,int lmt){ if (bl[u]!=bl[fa[u]]) return solve(bl[u],lmt); int ret=w[u]>lmt; for (int i=g[u];i;i=e[i].next)if (fa[e[i].adj]==u)ret+=query(e[i].adj,lmt); return ret; } void modify(int u,int x){ int p; for (int i=0;i<sz[bl[u]];++i) if (seq[bl[u]][i]==w[u]){p=i;break;} w[u]=x;seq[bl[u]][p]=x; refresh(bl[u],p); } void create(int u,int x){ AddEdge(u,++n);fa[n]=u;w[n]=x; int tmp=cnt; newnode(n); seq[bl[n]].push_back(w[n]); refresh(bl[n],sz[bl[n]]-1); if (tmp<cnt) nxt[bl[u]].push_back(cnt); } void dfs_update(int u,int last,int now){ bl[u]=now; for (int i=g[u];i;i=e[i].next)if (fa[e[i].adj]==u) if (bl[e[i].adj]==last) dfs_update(e[i].adj,last,now); } void cut(int u){ int lst=bl[u]; if (bl[fa[u]]!=bl[u]){ int f=bl[fa[u]]; for (vector<int>::iterator it=nxt[f].begin();it!=nxt[f].end();++it) if ((*it)==lst){nxt[f].erase(it);break;} fa[u]=0;return; } top[++cnt]=u; fa[u]=0; dfs_update(u,lst,cnt); prepare(lst); prepare(cnt); } int main(){ n=read(); memset(g,0,sizeof(g));m=1; for (int i=1;i<n;++i) AddEdge(read(),read()); for (int i=1;i<=n;++i) w[i]=read(); fa[1]=0;bl[0]=0;sz[0]=KK;cnt=0; dfs(1); int lastans=0; for (int i=1;i<=cnt;++i) prepare(i); for (int Q=read();Q;Q--){ int op=read(),u=read()^lastans,x; if (op<3) x=read()^lastans; else cut(u); if (op==0) printf("%d\n",lastans=query(u,x)); else if (op==1) modify(u,x); else if (op==2) create(u,x); } return 0; }