bzoj 4129: Haruna’s Breakfast 树上带修改莫队+分块
2017-05-26 20:52
411 查看
题意
有一棵树,每个节点有点权,要求资瓷单点修改和查询一条链上的mex。n,m<=50000
分析
一开始想到了树上带修改莫队+分块,但是觉得应该还有更简单的办法,结果发现就是这样。。。权当是复习树上莫队和带修改莫队吧。
树上莫队就是把这棵树的括号序(注意不是欧拉序)求出来然后就变成序列莫队了。
带修改的话就是加多一维表示修改到哪里。
其他的就是裸的求mex了。
没想到打的这么顺手。。。
一开始WA的原因是算mex的时候没有把n算进去。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=50005; int n,m,cnt,last ,f1,f[N*2],fa [20],block,tot ,t ,a ,bel[N*2],fir ,sec ,q1,c1,dep ,sta[2005],end[2005]; bool vis ; struct edge{int to,next;}e[N*2]; struct que{int l,r,x,id,lca,ans;}q ; struct oper{int x,y;}cha ; int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void addedge(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } void dfs(int x) { for (int i=1;i<=16;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; dep[x]=dep[fa[x][0]]+1;f[++f1]=x;fir[x]=f1;bel[f1]=(f1+block-1)/block; for (int i=last[x];i;i=e[i].next) { if (e[i].to==fa[x][0]) continue; fa[e[i].to][0]=x; dfs(e[i].to); } f[++f1]=x;sec[x]=f1;bel[f1]=(f1+block-1)/block; } int get_lca(int x,int y) { if (dep[x]<dep[y]) swap(x,y); for (int i=16;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; if (x==y) return x; for (int i=16;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } bool cmp(que a,que b) { return bel[a.l]<bel[b.l]||bel[a.l]==bel[b.l]&&bel[a.r]<bel[b.r]||bel[a.l]==bel[b.l]&&bel[a.r]==bel[b.r]&&bel[a.x]<bel[b.x]; } bool cmpid(que a,que b) { return a.id<b.id; } void updata(int x) { vis[x]=1-vis[x]; if (a[x]>n) return; if (!vis[x]) { t[a[x]]--; if (!t[a[x]]) tot[bel[a[x]]]--; } else { if (!t[a[x]]) tot[bel[a[x]]]++; t[a[x]]++; } } void change(int x) { if (vis[cha[x].x]) updata(cha[x].x),swap(a[cha[x].x],cha[x].y),updata(cha[x].x); else swap(a[cha[x].x],cha[x].y); } int query() { for (int i=1;;i++) if (tot[i]<end[i]-sta[i]+1) { for (int j=sta[i];j<=end[i];j++) if (!t[j]) return j-1; } } void solve() { for (int i=1,l=1,r=0,x=0;i<=q1;i++) { for (;r<q[i].r;r++) updata(f[r+1]); for (;l>q[i].l;l--) updata(f[l-1]); for (;r>q[i].r;r--) updata(f[r]); for (;l<q[i].l;l++) updata(f[l]); for (;x<q[i].x;x++) change(x+1); for (;x>q[i].x;x--) change(x); if (!vis[q[i].lca]) updata(q[i].lca),q[i].ans=query(),updata(q[i].lca); else q[i].ans=query(); } } int main() { n=read();m=read();block=pow(1.0*n*n,1.0/3); for (int i=1;i<=n;i++) a[i]=read()+1; for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y); } dfs(1); for (int i=1;i<=n+1;i++) { if (!sta[bel[i]]) sta[bel[i]]=i; end[bel[i]]=i; } for (int i=1;i<=m;i++) { int op=read(),x=read(),y=read(); if (!op) cha[++c1].x=x,cha[c1].y=y+1; else { q[++q1].x=c1;q[q1].lca=get_lca(x,y);q[q1].id=i; if (q[q1].lca==x||q[q1].lca==y) q[q1].l=min(fir[x],fir[y]),q[q1].r=max(fir[x],fir[y]); else { if (sec[x]<fir[y]) q[q1].l=sec[x],q[q1].r=fir[y]; else q[q1].l=sec[y],q[q1].r=fir[x]; } } } sort(q+1,q+q1+1,cmp); solve(); sort(q+1,q+q1+1,cmpid); for (int i=1;i<=q1;i++) printf("%d\n",q[i].ans); return 0; }
相关文章推荐
- 【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队+权值分块)
- bzoj 4129: Haruna’s Breakfast (带修改树上莫队+分块)
- [BZOJ4129]-Haruna’s Breakfast-带修改树上莫队+分块
- BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]
- 【BZOJ4129】Haruna’s Breakfast,树上带修莫队+权值分块求mex
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队+分块)
- bzoj 4129 Haruna’s Breakfast 树上莫队
- bzoj 4129 Haruna’s Breakfast 树上莫队
- [BZOJ]4129: Haruna’s Breakfast 树上带修改莫队+分块
- 【树上莫队】【带修莫队】【权值分块】bzoj4129 Haruna’s Breakfast
- 【bzoj4129】Haruna’s Breakfast 树上莫队+分块
- BZOJ 4129 Haruna’s Breakfast 树上莫队
- [BZOJ4129]Haruna’s Breakfast(树上莫队+分块)
- 【BZOJ】4129: Haruna’s Breakfast 树分块+带修改莫队算法
- 树上(带修改)莫队算法-- bzoj4129 && bzoj3757
- 【BZOJ4129】Haruna’s Breakfast(树上莫队)
- BZOJ 4129 Haruna’s Breakfast 带修改树上莫队+分块
- BZOJ 4129 Haruna’s Breakfast - 带修树上莫队+分块
- BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)