【BZOJ4129】Haruna’s Breakfast(樹上莫隊)
阿新 • • 發佈:2018-04-07
mex 端點 ble Go != gis odi down 分塊
接下來n-1行,每行包括兩個整數u,v,代表樹上的一條邊。
接下來m 行,每行包括三個整數
0 u x 代表將結點u的食材的美味度修改為 x。
1 u v 代表詢問以u,v 為端點的鏈的mex值。
【BZOJ4129】Haruna’s Breakfast(樹上莫隊)
題面
BZOJ
Description
Haruna每天都會給提督做早餐! 這天她發現早飯的食材被調皮的 Shimakaze放到了一棵
樹上,每個結點都有一樣食材,Shimakaze要考驗一下她。
每個食材都有一個美味度,Shimakaze會進行兩種操作:
1、修改某個結點的食材的美味度。
2、對於某條鏈,詢問這條鏈的美味度集合中,最小的未出現的自然數是多少。即mex值。
請你幫幫Haruna吧。
Input
第一行包括兩個整數n,m,代表樹上的結點數(標號為1~n)和操作數。
第二行包括n個整數a1...an,代表每個結點的食材初始的美味度。
接下來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
題解
求\(mex\)
如果放在序列上做很顯然是裸的莫隊+對數字分塊
放在樹上面就樹上莫隊啊。。。
大於\(n\)的值對答案沒有任何影響,直接丟掉就行了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 55555
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,m,blk;
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
int dfn[MAX],G[MAX],tim,gr,f[16][MAX],S[MAX],top,dep[MAX];
int dfs(int u,int ff)
{
f[0][u]=ff;dfn[u]=++tim;dep[u]=dep[ff]+1;
for(int i=1;i<=15;++i)f[i][u]=f[i-1][f[i-1][u]];
int ret=0;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff)continue;
ret+=dfs(v,u);
if(ret>=blk){++gr;while(ret--)G[S[top--]]=gr;ret=0;}
}
S[++top]=u;
return ret+1;
}
struct modify{int x,a,b;}p[MAX];
struct Query{int id,u,v,lb,rb,lm;}q[MAX];
bool operator<(Query a,Query b)
{
if(a.lb!=b.lb)return a.lb<b.lb;
if(a.rb!=b.rb)return a.rb<b.rb;
return a.lm<b.lm;
}
int LCA(int u,int v)
{
if(dep[u]<dep[v])swap(u,v);
for(int i=15;~i;--i)if(dep[f[i][u]]>=dep[v])u=f[i][u];
if(u==v)return u;
for(int i=15;~i;--i)if(f[i][u]!=f[i][v])u=f[i][u],v=f[i][v];
return f[0][u];
}
int cnt1,cnt2,a[MAX],pre[MAX],nblk;
int sum[MAX],sblk[MAX];
bool vis[MAX];
void Change(int x)
{
if(a[x]>n)return;
if(vis[x])--sum[a[x]]?x:--sblk[(a[x])/nblk];
else sum[a[x]]++?x:++sblk[(a[x])/nblk];
vis[x]^=1;
}
void ModifyLink(int u,int v)
{
while(u!=v)
if(dep[u]<dep[v])Change(v),v=f[0][v];
else Change(u),u=f[0][u];
}
int Mex()
{
for(int i=0;;++i)
if(sblk[i]!=nblk)
for(int j=0;j<nblk;++j)
if(!sum[i*nblk+j])return i*nblk+j;
}
void ModifyVal(int x,int c)
{
if(!vis[x])a[x]=c;
else Change(x),a[x]=c,Change(x);
}
int Ans[MAX];
int main()
{
n=read();m=read();blk=pow(n,0.66);nblk=sqrt(n);
for(int i=1;i<=n;++i)a[i]=pre[i]=read();
for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v),Add(v,u);
dfs(1,0);
for(int i=1;i<=m;++i)
{
int opt=read(),u=read(),v=read();
if(opt==0)p[++cnt2]=(modify){u,pre[u],v},pre[u]=v;
else
{
if(dfn[u]>dfn[v])swap(u,v);
++cnt1,q[cnt1]=(Query){cnt1,u,v,G[u],G[v],cnt2};
}
}
sort(&q[1],&q[cnt1+1]);
int lca=LCA(q[1].u,q[1].v),pos=0;
while(pos<q[1].lm)++pos,ModifyVal(p[pos].x,p[pos].b);
ModifyLink(q[1].u,q[1].v);Change(lca);Ans[q[1].id]=Mex();Change(lca);
for(int i=2;i<=cnt1;++i)
{
while(pos<q[i].lm)++pos,ModifyVal(p[pos].x,p[pos].b);
while(pos>q[i].lm)ModifyVal(p[pos].x,p[pos].a),pos--;
ModifyLink(q[i-1].u,q[i].u);ModifyLink(q[i-1].v,q[i].v);
lca=LCA(q[i].u,q[i].v);
Change(lca);Ans[q[i].id]=Mex();Change(lca);
}
for(int i=1;i<=cnt1;++i)printf("%d\n",Ans[i]);
return 0;
}
【BZOJ4129】Haruna’s Breakfast(樹上莫隊)