bzoj 4129: Haruna’s Breakfast
2018-07-15 11:46
274 查看
Description
Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了一棵树上,每个结点都有一样食材,Shimakaze要考验一下她。
每个食材都有一个美味度,Shimakaze会进行两种操作:
1、修改某个结点的食材的美味度。
2、对于某条链,询问这条链的美味度集合中,最小的未出现的自然数是多少。即mex值。
请你帮帮Haruna吧。
Solution
树上莫队按照老方法分块,块大小为 \(n^{\frac{2}{3}}\)
然后对于求 \(mex\) 的方法,我不晓得怎么写,于是就写了一个指针移动带 \(log\) 的方法
树状数组维护 \(mex\) 数,我们二分到最后一个满足 \(sum[i]=i+1\) 的位置, \(sum[i]\) 表示小于 \(i\) 的数出现的总次数(出现多次算一次),答案就是 \(i+1\),用树状数组维护 \(sum\) 即可
注意一些优化:大于 \(n\) 的值是不可能成为 \(mex\) 的,可以直接去掉
复杂度 \(O(n^{\frac{5}{3}}*logn)\)
树剖写挂T飞了,调了好久
关于树上莫队,还有一些个人的理解:
序列上的莫队之所以可以直接移动指针,是因为是有序的(假设 \(l\) 指针小于等于 \(i\), 也就是说 \(i+1\) 被算进去了 \(i\) 一定也被算进去了)
而树上就不一定满足(一个点可以被多次算入贡献),所以我们把改为一个存在性问题,给每一个点一个 \(vis\) 标记,访问第一次加入,访问第二次就删除,这样就好了
这正好满足异或运算的规律,所以转移过程可以用异或运算来推导,利用异或运算的交换率和结合率就可以实现序列莫队的复杂度了
#include<bits/stdc++.h> #define RG register using namespace std; const int N=50010; int n,a ,Q,head ,nxt[N*2],to[N*2],num=0,fa ,B,st ,top=0; int b ,v ,cnt=0,sz ,dep ,Top ,son ,siz ,tp; inline void link(int x,int y){ nxt[++num]=head[x];to[num]=y;head[x]=num; nxt[++num]=head[y];to[num]=x;head[y]=num; } inline void dfs(int x){ siz[x]=1; for(int u,i=head[x];i;i=nxt[i]){ if((u=to[i])==fa[x])continue; fa[u]=x;dep[u]=dep[x]+1;dfs(u); sz[x]+=sz[u];siz[x]+=siz[u]; if(sz[x]>=B){ cnt++; while(sz[x])b[st[top--]]=cnt,sz[x]--; } if(siz[u]>siz[son[x]])son[x]=u; } st[++top]=x;sz[x]++; } inline void dfs2(int x,int tp){ Top[x]=tp; if(son[x])dfs2(son[x],tp); for(int i=head[x];i;i=nxt[i]) if(to[i]!=son[x] && to[i]!=fa[x])dfs2(to[i],to[i]); } struct data{ int x,y,t,id; bool operator <(const data &p)const{ if(b[x]!=b[p.x])return b[x]<b[p.x]; if(b[y]!=b[p.y])return b[y]<b[p.y]; return t<p.t; } }S ,T ; bool vis ;int t ,tr ,ans ,pre ; inline void add(int x,int t){ for(RG int i=x;i<=n;i+=(i&(-i)))tr[i]+=t; } inline int qry(int x){ int ret=0; for(RG int i=x;i>=1;i-=(i&(-i)))ret+=tr[i]; return ret; } inline void rev(int x){ if(a[x]>n)return ; vis[x]^=1; if(vis[x]){t[a[x]]++;if(t[a[x]]==1)add(a[x],1);} else{t[a[x]]--;if(t[a[x]]==0)add(a[x],-1);} } inline void upd(int x,int y){ while(x!=y){ if(dep[x]<dep[y])swap(x,y); rev(x);x=fa[x]; } } inline void change(int x,int y){ if(vis[x])rev(x),a[x]=y,rev(x); else a[x]=y; } inline int LCA(int x,int y){ while(Top[x]!=Top[y]){ if(dep[Top[x]]<dep[Top[y]])swap(x,y); x=fa[Top[x]]; } return dep[x]<dep[y]?x:y; } inline int getans(){ int l=1,r=n,mid,ret=0; while(l<=r){ mid=(l+r)>>1; if(qry(mid)>v[mid])ret=mid,l=mid+1; else r=mid-1; } return v[ret]+1; } int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); int x,y,op; cin>>n>>Q; for(B=1;1ll*B*B*B<=1ll*n*n;B++); for(int i=1;i<=n;i++)scanf("%d",&a[i]),v[i]=i-1; v[0]=-1; for(int i=1;i<=n;i++)pre[i]=a[i]=lower_bound(v+1,v+n+1,a[i])-v; for(int i=1;i<n;i++)scanf("%d%d",&x,&y),link(x,y); dfs(1);dfs2(1,1); if(top){ cnt++; while(top)b[st[top--]]=cnt; } int p=0,q=0,t=0; for(int i=1;i<=Q;i++){ scanf("%d%d%d",&op,&x,&y); if(op==0)y=lower_bound(v+1,v+n+1,y)-v; if(op==0)S[++p]=(data){x,y,p,pre[x]},pre[x]=y; else { if(b[x]>b[y])swap(x,y); T[++q]=(data){x,y,p,q}; } } if(!q)exit(0); sort(T+1,T+q+1); while(t<T[1].t)t++,change(S[t].x,S[t].y); upd(T[1].x,T[1].y); int lca=LCA(T[1].x,T[1].y);rev(lca); ans[T[1].id]=getans();rev(lca); for(int i=2;i<=q;i++){ while(t<T[i].t)t++,change(S[t].x,S[t].y); while(t>T[i].t)change(S[t].x,S[t].id),t--; upd(T[i-1].x,T[i].x); upd(T[i-1].y,T[i].y); lca=LCA(T[i].x,T[i].y);rev(lca); ans[T[i].id]=getans();rev(lca); } for(int i=1;i<=q;i++)printf("%d\n",ans[i]); return 0; }
相关文章推荐
- 【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
- bzoj 4129: 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
- [BZOJ4129]Haruna’s Breakfast(树上带修改莫队+分块)
- bzoj 4129: Haruna's Breakfast
- [BZOJ4129]Haruna’s Breakfast(树上莫队+分块)
- BZOJ 4129 Haruna’s Breakfast (分块 + 带修莫队)
- [BZOJ4129]-Haruna’s Breakfast-带修改树上莫队+分块
- 【BZOJ4129】Haruna’s Breakfast(树上莫队)