1. 程式人生 > >bzoj4129 Haruna’s Breakfast

bzoj4129 Haruna’s Breakfast

-- tchar scrip 操作 分塊 str def 思路 from

Description

Haruna每天都會給提督做早餐! 這天她發現早飯的食材被調皮的 Shimakaze放到了一棵樹上,每個結點都有一樣食材,Shimakaze要考驗一下她。

每個食材都有一個美味度,Shimakaze會進行兩種操作: 1、修改某個結點的食材的美味度。 2、對於某條鏈,詢問這條鏈的美味度集合中,最小的未出現的自然數是多少。即mex值。 請你幫幫Haruna吧。

Input

第一行包括兩個整數n,m,代表樹上的結點數(標號為1~n)和操作數。

第二行包括n個整數a1...an,代表每個結點的食材初始的美味度。 接下來n-1行,每行包括兩個整數u,v,代表樹上的一條邊。 接下來m 行,每行包括三個整數 0 u x 代表將結點u的食材的美味度修改為 x。 1 u v 代表詢問以u,v 為端點的鏈的mex值。

Output

對於每次詢問,輸出該鏈的mex值。

Sample Input

10 10
1 0 1 0 2 4 4 0 1 0
1 2
2 3
2 4
2 5
1 6
6 7
2 8
3 9
9 10
0 7 14
1 6 6
0 4 9
1 2 2
1 1 8
1 8 3
0 10 9
1 3 5
0 10 0
0 7 7

Sample Output

0
1
2
2
3

HINT

1<=n<=5*10^4

1<=m<=5*10^4 0<=ai<=10^9

正解:樹上帶修改莫隊+分塊。

我只是感覺自己可能會忘記套路然後就又做了一道題。。

這題莫隊的思路還是比較顯然的,問題主要是如何查詢。

我們把權值按照根號$n$分塊。很顯然,$mex<=n$,所以我們只需要把$<=n$的數標記就行了。

查詢時我們從小到大枚舉每一個塊,如果當前這個塊沒有滿,那麽再枚舉塊內的每一個元素,這樣我們就能很方便地找到答案了。

  1 //It is made by wfj_2048~
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <complex>
  5 #include <cstring>
  6
#include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (100010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 struct upd{ int u,v,x; }q1[N]; 24 struct que{ int i,tim,u,v; }q2[N]; 25 struct edge{ int nt,to; }g[2*N]; 26 27 int head[N],top[N],fa[N],son[N],dep[N],dfn[N],sz[N],bl[N],st[N],vis[N],val[N],sum[N],la[N],a[N],ans[N],n,m,num,Q1,Q2,Tp,Lca,cnt,Bl,totb,block; 28 29 il int gi(){ 30 RG int x=0,q=1; RG char ch=getchar(); 31 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 32 if (ch==-) q=-1,ch=getchar(); 33 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 34 return q*x; 35 } 36 37 il void insert(RG int from,RG int to){ 38 g[++num]=(edge){head[from],to},head[from]=num; return; 39 } 40 41 il int cmp(const que &a,const que &b){ 42 if (bl[a.u]==bl[b.u] && bl[a.v]==bl[b.v]) return a.tim<b.tim; 43 if (bl[a.u]==bl[b.u]) return bl[a.v]<bl[b.v]; return bl[a.u]<bl[b.u]; 44 } 45 46 il void dfs1(RG int x,RG int p){ 47 dep[x]=dep[p]+1,fa[x]=p,sz[x]=1; RG int v; 48 for (RG int i=head[x];i;i=g[i].nt){ 49 v=g[i].to; if (v==p) continue; 50 dfs1(v,x),sz[x]+=sz[v]; 51 if (sz[son[x]]<=sz[v]) son[x]=v; 52 } 53 return; 54 } 55 56 il void dfs2(RG int x,RG int p,RG int anc){ 57 top[x]=anc,dfn[x]=++cnt; RG int tp=Tp,v; 58 if (son[x]) dfs2(son[x],x,anc); if (Tp-tp>block) ++totb; 59 while (Tp-tp>block) bl[st[Tp--]]=totb; 60 for (RG int i=head[x];i;i=g[i].nt){ 61 v=g[i].to; if (v==p || v==son[x]) continue; 62 tp=Tp,dfs2(v,x,v); if (Tp-tp>block) ++totb; 63 while (Tp-tp>block) bl[st[Tp--]]=totb; 64 } 65 st[++Tp]=x; return; 66 } 67 68 il int lca(RG int u,RG int v){ 69 while (top[u]!=top[v]){ 70 if (dep[top[u]]<dep[top[v]]) swap(u,v); u=fa[top[u]]; 71 } 72 return dep[u]<dep[v] ? u : v; 73 } 74 75 il void update(RG int x){ 76 if (!vis[x]){ 77 vis[x]=1; if (a[x]>n) return; 78 ++val[a[x]]; if (val[a[x]]==1) ++sum[a[x]/Bl]; 79 } else{ 80 vis[x]=0; if (a[x]>n) return; 81 --val[a[x]]; if (!val[a[x]]) --sum[a[x]/Bl]; 82 } 83 return; 84 } 85 86 il void modify(RG int x,RG int v){ 87 if (!vis[x]) a[x]=v; else update(x),a[x]=v,update(x); return; 88 } 89 90 il void change(RG int u,RG int v){ 91 while (u!=v){ 92 if (dep[u]>dep[v]) update(u),u=fa[u]; else update(v),v=fa[v]; 93 } 94 return; 95 } 96 97 il int query(){ 98 for (RG int i=0;;++i) 99 if (sum[i]!=Bl) for (RG int j=i*Bl;;++j) if (!val[j]) return j; 100 } 101 102 il void work(){ 103 n=gi(),m=gi(),block=pow(n,0.6),Bl=sqrt(n); 104 for (RG int i=1;i<=n;++i) a[i]=gi(),la[i]=a[i]; 105 for (RG int i=1,u,v;i<n;++i) u=gi(),v=gi(),insert(u,v),insert(v,u); 106 dfs1(1,0),dfs2(1,0,1),cnt=0; if (Tp) ++totb; while (Tp) bl[st[Tp--]]=totb; 107 for (RG int i=1,op,u,v;i<=m;++i){ 108 op=gi(),u=gi(),v=gi(); 109 if (!op) q1[++Q1]=(upd){u,v,la[u]},la[u]=v; 110 else{ if (dfn[u]>dfn[v]) swap(u,v); q2[++Q2]=(que){Q2,Q1,u,v}; } 111 } 112 sort(q2+1,q2+Q2+1,cmp); 113 while (cnt<q2[1].tim) ++cnt,modify(q1[cnt].u,q1[cnt].v); 114 change(q2[1].u,q2[1].v),Lca=lca(q2[1].u,q2[1].v); 115 update(Lca),ans[q2[1].i]=query(),update(Lca); 116 for (RG int i=2;i<=Q2;++i){ 117 while (cnt<q2[i].tim) ++cnt,modify(q1[cnt].u,q1[cnt].v); 118 while (cnt>q2[i].tim) modify(q1[cnt].u,q1[cnt].x),--cnt; 119 change(q2[i-1].u,q2[i].u),change(q2[i-1].v,q2[i].v); 120 Lca=lca(q2[i].u,q2[i].v),update(Lca),ans[q2[i].i]=query(),update(Lca); 121 } 122 for (RG int i=1;i<=Q2;++i) printf("%d\n",ans[i]); return; 123 } 124 125 int main(){ 126 File("mex"); 127 work(); 128 return 0; 129 }

bzoj4129 Haruna’s Breakfast