【树上莫队】【带修莫队】【权值分块】bzoj4129 Haruna’s Breakfast
2015-06-18 21:45
411 查看
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define N 50001 int v[N<<1],en,first ,next[N<<1]; void AddEdge(int U,int V) { v[++en]=V; next[en]=first[U]; first[U]=en; } int n,m,a ,b ; int eq,ec,blo,sz,siz ,top ,fa ,dep ,num ; void dfs(int U) { for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { fa[v[i]]=U; dep[v[i]]=dep[U]+1; if(siz[top[U]]<sz) { ++siz[top[U]]; top[v[i]]=top[U]; } dfs(v[i]); } } void df2(int U) { num[U]=blo; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&top[v[i]]==top[U]) df2(v[i]); } int lca(int U,int V) { while(U!=V) { if(top[U]!=top[V]) { if(dep[top[U]]<dep[top[V]]) swap(U,V); U=fa[top[U]]; } else { if(dep[U]<dep[V]) swap(U,V); U=fa[U]; } } return U; } struct UPT{int x,y,z;}CH ; struct ASK{int l,r,p,t;}Q ; bool operator < (const ASK &a,const ASK &b) { if(num[a.l]==num[b.l]) { if(num[a.r]==num[b.r]) return a.t<b.t; return num[a.r]<num[b.r]; } return num[a.l]<num[b.l]; } int nu2 ,r[230],l[230],sumv[230],bl2=1,T ; void makeblock() { int sz=sqrt(n); if(!sz) sz=0; r[0]=-1; for(;bl2*sz<n;++bl2) { l[bl2]=r[bl2-1]+1; r[bl2]=bl2*sz; for(int i=l[bl2];i<=r[bl2];++i) nu2[i]=bl2; } l[bl2]=r[bl2-1]+1; r[bl2]=n; for(int i=l[bl2];i<=r[bl2];++i) nu2[i]=bl2; } void Update(int x,int op) { if(x>=n) return; T[x]+=op; if(!T[x]) --sumv[nu2[x]]; else if(op==1&&T[x]==1) ++sumv[nu2[x]]; } bool vis ; void Work(int U,int V,int LCA) { while(U!=LCA) { vis[U]^=1; Update(a[U],vis[U]?1:-1); U=fa[U]; } while(V!=LCA) { vis[V]^=1; Update(a[V],vis[V]?1:-1); V=fa[V]; } } int Query() { for(int i=1;i<=bl2;++i) if(sumv[i]<r[i]-l[i]+1) for(int j=l[i];j<=r[i];++j) if(!T[j]) return j; } bool op ; int anss ; int main() { int x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<n;++i) { scanf("%d%d",&x,&y); AddEdge(x,y); AddEdge(y,x); } for(int i=1;i<=n;++i) { top[i]=i; siz[i]=1; } sz=(int)pow((double)n,2.0/3.0); dfs(1); for(int i=1;i<=n;++i) if(top[i]==i) { ++blo; df2(i); } memcpy(b,a,sizeof(int)*(n+1)); for(int i=1;i<=m;++i) { scanf("%d",&op[i]); if(!op[i]) { ++ec; scanf("%d%d",&CH[ec].x,&CH[ec].y); CH[ec].z=b[CH[ec].x]; b[CH[ec].x]=CH[ec].y; } else { ++eq; scanf("%d%d",&Q[eq].l,&Q[eq].r); Q[eq].t=ec; Q[eq].p=eq; } } makeblock(); sort(Q+1,Q+eq+1); for(int i=1;i<=Q[1].t;++i) a[CH[i].x]=CH[i].y; int LCA=lca(Q[1].l,Q[1].r); Work(Q[1].l,Q[1].r,LCA); Update(a[LCA],1); anss[Q[1].p]=Query(); Update(a[LCA],-1); for(int i=2;i<=eq;++i) { if(Q[i-1].t<Q[i].t) for(int j=Q[i-1].t+1;j<=Q[i].t;++j) { if(vis[CH[j].x]) { Update(CH[j].y,1); Update(a[CH[j].x],-1); } a[CH[j].x]=CH[j].y; } else for(int j=Q[i-1].t;j>Q[i].t;--j) { if(vis[CH[j].x]) { Update(CH[j].z,1); Update(a[CH[j].x],-1); } a[CH[j].x]=CH[j].z; } Work(Q[i-1].l,Q[i].l,lca(Q[i-1].l,Q[i].l)); Work(Q[i-1].r,Q[i].r,lca(Q[i-1].r,Q[i].r)); LCA=lca(Q[i].l,Q[i].r); Update(a[LCA],1); anss[Q[i].p]=Query(); Update(a[LCA],-1); } for(int i=1;i<=eq;++i) printf("%d\n",anss[i]); return 0; }
相关文章推荐
- 希捷个人云:家用NAS的解决方案
- [DP]三角形牧场
- Decision Boundaries for Deep Learning and other Machine Learning classifiers
- 【kd-tree】bzoj2716 [Violet 3]天使玩偶
- 【Linux 内核网络协议栈源码剖析】af_inet.c——INET Socket层(2)
- MyBatis数据持久化(六)resultMap使用
- MyBatis数据持久化(六)resultMap使用
- 最受欢迎的eclipse插件汇总
- Linux磁盘和文件系统
- MyBatis数据持久化(六)resultMap使用
- 学习笔记:axure 初级教程
- 返回一个二维整数数组中最大联通子数组的和
- http简介
- 【kd-tree】bzoj2648 SJY摆棋子
- gnome desktop environment
- github笔记
- 用命令行对closure compiler进行封装调用
- ReactiveCocoa框架菜鸟入门(五)——信号的FlattenMap与Map
- hdu 4651Partition(整数拆分模板题)
- 常见的算法题:逆行单一列表