[BZOJ4129]Haruna’s Breakfast(树上带修改莫队)

BZOJ3585,BZOJ2120,BZOJ3757三合一。

对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队。

这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度。

剩下的就是将分块、树上莫队、带修改莫队合在一起了。大概要实现一下几个函数:

插入某值、删除某值、查询MEX、加入一个修改操作、更改一个点产生的影响(可能加入可能删除)。

另外要注意两个经典易错处:修改操作要记录lst以方便撤销,lst初始就是读入的数值。左端点所在块编号比右端点大是交换左右端点。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 6 using namespace std;
 7 
 8 const int N=100010;
 9 int n,m,op,u,v,A,B,p[N],bel[N],vis[N],val[N],w[N],lst[N],ans[N],fa[N][20];
10 int cnt,top,bl,tot,s[510][510],stk[N],d[N],h[N],to[N<<1],nxt[N<<1];
11 struct P{ int op,x,y,t,lst,id; }a[N],b[N];
12 
13 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
14 
15 bool cmp(const P &a,const P &b){
16     if (bel[a.x]!=bel[b.x]) return bel[a.x]<bel[b.x];
17     if (bel[a.y]!=bel[b.y]) return bel[a.y]<bel[b.y];
18     return a.t<b.t;
19 }
20 
21 void dfs(int x){
22     d[x]=d[fa[x][0]]+1; int tmp=top;
23     rep(i,1,18) fa[x][i]=fa[fa[x][i-1]][i-1];
24     For(i,x) if ((k=to[i])!=fa[x][0]){
25         fa[k][0]=x; dfs(k);
26         if (top-tmp>=bl){ tot++; while (top>tmp) bel[stk[top--]]=tot; }
27     }
28     stk[++top]=x;
29 }
30 
31 int lca(int x,int y){
32     if (d[x]<d[y]) swap(x,y);
33     int t=d[x]-d[y];
34     for (int i=18; ~i; i--) if (t&(1<<i)) x=fa[x][i];
35     if (x==y) return x;
36     for (int i=18; ~i; i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
37     return fa[x][0];
38 }
39 
40 void add(int x){
41     if (x>n) return;
42     int t=x%bl; s[p[x]][t]++; if (s[p[x]][t]==1) w[p[x]]++;
43 }
44 
45 void del(int x){
46     if (x>n) return;
47     int t=x%bl; s[p[x]][t]--; if (s[p[x]][t]==0) w[p[x]]--;
48 }
49 
50 int que(){
51     rep(i,1,n/bl+1){
52         if (w[i]==bl) continue;
53         rep(j,(i-1)*bl,i*bl-1) if (!s[i][j%bl]) return j;
54     }
55     return (n/bl+1)*bl;
56 }
57 
58 void mdf(int x,int y){
59     if (!vis[x]){ val[x]=y; return; }
60     del(val[x]); val[x]=y; add(val[x]);
61 }
62 
63 void upd(int x){ vis[x]?del(val[x]):add(val[x]); vis[x]^=1; }
64 
65 void work(int x,int y){
66     for (; x!=y; upd(x),x=fa[x][0])
67         if (d[x]<d[y]) swap(x,y);
68 }
69 
70 void solve(){
71     int L=1,R=1,t=0;
72     rep(i,1,A){
73         while (t>a[i].t) mdf(b[t].x,b[t].lst),t--;
74         while (t<a[i].t) t++,mdf(b[t].x,b[t].y);
75         work(L,a[i].x); work(R,a[i].y); L=a[i].x; R=a[i].y;
76         int f=lca(L,R); upd(f); ans[a[i].id]=que(); upd(f);
77     }
78 }
79 
80 int main(){
81     freopen("bzoj4129.in","r",stdin);
82     freopen("bzoj4129.out","w",stdout);
83     scanf("%d%d",&n,&m); p[0]=1; bl=sqrt(n);
84     rep(i,1,n) scanf("%d",&val[i]),lst[i]=val[i],p[i]=i/bl+1;
85     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u);
86     dfs(1); while (top) bel[stk[top--]]=tot;
87     rep(i,1,m){
88         scanf("%d%d%d",&op,&u,&v);
89         if (op==1){
90             a[++A]=(P){op,u,v,B,0,A};
91             if (bel[u]>bel[v]) swap(a[A].x,a[A].y);
92         }else b[++B]=(P){op,u,v,B,lst[u],0},lst[u]=v;
93     }
94     sort(a+1,a+A+1,cmp); solve();
95     rep(i,1,A) printf("%d\n",ans[i]);
96     return 0;
97 }

 

posted @ 2019-02-20 20:04  HocRiser  阅读(162)  评论(0编辑  收藏  举报