[BZOJ4129]Haruna’s Breakfast(树上莫队+分块)
2018-01-29 21:36
423 查看
题目:
我是超链接题解:
这一看就是树上莫队+修改没跑了吧,区间转移还是统计每个数字的个数吧,但是这个查询?朴素的想法就是按照权值分块了,看看这个权值块里数值是不是全的,不是全的就枚举,这样可以实现O(n−−√)O(n)枚举,O(1)O(1)修改,这个块略大啊,存num也不好存,但实际上,我们只需要存[0,n]之内的权值就好了,因为只有n个数,mex肯定出在这个区间内,其他的丢掉就好
哇哇哇1A辣
代码:
#include <cmath> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; const int sz=24; const int N=50005; struct hh{int x,y,id,t;}ch ,q ; int a ,tot,nxt[N*2],point ,v[N*2],pos ,ks,nn,top,n,ans ; int f [sz],mi[sz],h ,num ,belong ,have ,dfn ,block,stack ,cnt; bool vis ; int cmp(hh a,hh b) { return pos[a.x]<pos[b.x] || (pos[a.x]==pos[b.x] && dfn[a.y]<dfn[b.y]) || (pos[a.x]==pos[b.x] && dfn[a.y]==dfn[b.y] && a.t<b.t); } void addline(int x,int y) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; } void dfs(int x,int fa) { dfn[x]=++nn; h[x]=h[fa]+1;int bottom=top; for (int i=1;i<sz;i++) if (h[x]<mi[i]) break; else f[x][i]=f[f[x][i-1]][i-1]; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { f[v[i]][0]=x;dfs(v[i],x); if (top-bottom>=block) { cnt++; while (top!=bottom) pos[stack[top--]]=cnt; } } stack[++top]=x; } int lca(int x,int y) { if (h[x]<h[y]) swap(x,y); int k=h[x]-h[y]; for (int i=0;i<sz;i++) if (k&(1<<i)) x=f[x][i]; if (x==y) return x; for (int i=sz-1;i>=0;i--) if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } void change(int x) { if (vis[x]) { vis[x]=0; if (a[x]<n) { num[a[x]]--; if (!num[a[x]]) have[belong[a[x]]]--; } }else { vis[x]=1; if (a[x]<n) { num[a[x]]++; if (num[a[x]]==1) have[belong[a[x]]]++; } } } void reverse(int x,int y) { while (x!=y) if (h[x]<h[y]) change(y),y=f[y][0]; else change(x),x=f[x][0]; } void modi(int now) { if (vis[ch[now].x]) { change(ch[now].x); swap(a[ch[now].x],ch[now].y); change(ch[now].x); }else swap(a[ch[now].x],ch[now].y); } int ask() { for (int i=1;i<=ks;i++) if (have[i]!=block) { int l=(i-1)*block,r=i*block-1; for (int j=l;j<=r;j++) if (!num[j]) return j; } return n; } int main() { int x,y,tim=0,wh=0,m;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); addline(x,y); } mi[0]=1;for (int i=1;i<sz;i++) mi[i]=mi[i-1]*2; dfs(1,0); cnt++;while (top) pos[stack[top--]]=cnt; block=sqrt(n);ks=n/block;if (n%block) ks++; for (int i=0;i<n;i++) belong[i]=i/block+1; for (int i=1;i<=m;i++) { int id;scanf("%d%d%d",&id,&x,&y); if (id==0) ch[++tim].x=x,ch[tim].y=y; else { if (dfn[x]>dfn[y]) swap(x,y); q[++wh].x=x;q[wh].y=y;q[wh].t=tim;q[wh].id=wh; } } sort(q+1,q+wh+1,cmp); int t=lca(q[1].x,q[1].y),now=0; while (now<q[1].t) modi(++now); reverse(q[1].x,q[1].y); change(t); ans[q[1].id]=ask(); for (int i=2;i<=wh;i++) { change(t); reverse(q[i-1].x,q[i].x); reverse(q[i-1].y,q[i].y); while (now<q[i].t) modi(++now); while (now> ec59 q[i].t) modi(now--); t=lca(q[i].x,q[i].y); change(t); ans[q[i].id]=ask(); } for (int i=1;i<=wh;i++) printf("%d\n",ans[i]); }
相关文章推荐
- 【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块
- 【树上莫队】【带修莫队】【权值分块】bzoj4129 Haruna’s Breakfast
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队+分块)
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队+权值分块)
- [BZOJ4129]-Haruna’s Breakfast-带修改树上莫队+分块
- 【bzoj4129】Haruna’s Breakfast 树上莫队+分块
- bzoj 4129: 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 树上莫队
- bzoj 4129 Haruna’s Breakfast 树上莫队
- BZOJ 4129 Haruna’s Breakfast 带修改树上莫队+分块
- BZOJ 4129 Haruna’s Breakfast 树上莫队
- [bzoj 4129]Haruna’s Breakfast
- BZOJ4129 : Haruna’s Breakfast
- [BZOJ]4129: Haruna’s Breakfast 树上带修改莫队+分块
- 树上(带修改)莫队算法-- bzoj4129 && bzoj3757