首页 > 代码库 > 【树上莫队】bzoj3757 苹果树
【树上莫队】bzoj3757 苹果树
学习这位神犇的:http://blog.csdn.net/jiangyuze831/article/details/41476865
注意:
①排序时第一关键字是左端点所在块编号(块状树),第二关键字是右端点dfs序。
②维护的当前链不能包括lca(l,r),但最后要计算上lca(l,r)的答案。
③对l->l‘/r->r‘取反的时候也不能取反lca(l,l‘)/lca(r,r‘)。
#include<cstdio>#include<cmath>#include<algorithm>using namespace std;#define N 50001#define M 100001int n,m;int first[N],en,next[N<<1],dfsn[N],v[N<<1],fa[N],bel[N],dep[N],siz[N],cnt,top[N];int x,y,root,sz,col[N],Time[N],ans,anss[M];bool vis[N];struct ASK{int l,r,a,b,id;void Read(){scanf("%d%d%d%d",&l,&r,&a,&b);}}Q[M];bool operator < (const ASK &a,const ASK &b){return bel[a.l]!=bel[b.l] ? bel[a.l]<bel[b.l] : dfsn[a.r]<dfsn[b.r];}void AddEdge(const int &U,const int &V){ v[++en]=V; next[en]=first[U]; first[U]=en;}void dfs(int cur){ dfsn[cur]=++cnt; for(int i=first[cur];i;i=next[i]) if(v[i]!=fa[cur]) { dep[v[i]]=dep[cur]+1; fa[v[i]]=cur; dfs(v[i]); }}void makeblock(int cur){ for(int i=first[cur];i;i=next[i]) if(v[i]!=fa[cur]) { if(siz[bel[cur]]<sz) { ++siz[bel[cur]]; bel[v[i]]=bel[cur]; top[v[i]]=top[cur]; } makeblock(v[i]); }}int QLCA(int U,int V){ while(U!=V) { if(top[U]==top[V]) { if(dep[U]<dep[V]) swap(U,V); U=fa[U]; } else { if(dep[top[U]]<dep[top[V]]) swap(U,V); U=fa[top[U]]; } } return U;}void update(const int &Col,const int &op){ Time[Col]+=op; if(!Time[Col]) --ans; else if(Time[Col]==1&&op==1) ++ans;}void Work(int U,int V,int lca) { while(U!=lca) { vis[U]^=1; update(col[U],vis[U]?1:-1); U=fa[U]; } while(V!=lca) { vis[V]^=1; update(col[V],vis[V]?1:-1); V=fa[V]; }} void Solve(const int &p) { int lca=QLCA(Q[p].l,Q[p].r); if(p==1) Work(Q[p].l,Q[p].r,lca); else { Work(Q[p-1].l,Q[p].l,QLCA(Q[p-1].l,Q[p].l)); Work(Q[p-1].r,Q[p].r,QLCA(Q[p-1].r,Q[p].r)); } update(col[lca],1); anss[Q[p].id]=ans; if(Q[p].a!=Q[p].b) anss[Q[p].id]-=(Time[Q[p].a]&&Time[Q[p].b]); update(col[lca],-1);} int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&col[i]); for(int i=1;i<=n;++i) { scanf("%d%d",&x,&y); if(!x) root=y; else if(!y) root=x; else { AddEdge(x,y); AddEdge(y,x); } } dfs(root); for(int i=1;i<=n;i++) { siz[bel[i]=dfsn[i]]=1; top[i]=i; } sz=(((int)sqrt(n))<<1); makeblock(root); for(int i=1;i<=m;++i) Q[i].Read(),Q[i].id=i; sort(Q+1,Q+m+1); for(int i=1;i<=m;++i) Solve(i); for(int i=1;i<=m;++i) printf("%d\n",anss[i]); return 0;}
【树上莫队】bzoj3757 苹果树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。