【Learning】倍增求LCA题目汇总
2017-12-02 08:18
148 查看
这里是我倍增的练习记录,大多都是水题……也有一些混合了其它算法的。= = silly……顺序可能有些错乱,并不是按照难度来排的。
T1 hdu3710 倍增+树剖
T2 luogu3379 模板题
T3 zoj3195 模板题
T4 bzoj2588 主席树+树上差分+倍增lca
[b]T5 bzoj1787&&bzoj1832 模版题
T6 hdu2586 模版题
T7 poj1330 模版题
T8 gdgzoi2232祖孙询问 模版题
这么多水题忽然好颓废啊!
T9 luogu1967&&xsy2018 倍增+最大生成树
T10 CF587C&&xsy2414 倍增+归并
T11 bzoj3545&&bzoj3551 并查集+谜之建树+倍增+线段树
终于写完了,好嗨森!
T1 hdu3710 倍增+树剖
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N=20005,M=100005,inf=2139062143; int t,n,m,u,v,d,f,ns,rt,cnt,idx,head ,to[N*2],nxt[N*2]; int dep ,fa [20],siz ,son ,dfn ,pos ,top ; int minn ,minv[N*4],tag[N*4]; bool use[M]; int s,mst,smst,pa ,w ,sont ,num ; struct edge{ int u,v,d; bool operator < (const edge &x)const{ return d<x.d; } }e[M]; vector<edge> link ,edges; void init(){ smst=idx=cnt=rt=0; memset(use,0,sizeof(use)); memset(head,0,sizeof(head)); memset(dep,0,sizeof(dep)); memset(fa,0,sizeof(fa)); memset(son,0,sizeof(son)); memset(sont,0,sizeof(sont)); memset(w,0,sizeof(w)); memset(minv,127,sizeof(minv)); memset(tag,127,sizeof(tag)); for(int i=1;i<=n;i++){ pa[i]=i; link[i].clear(); } } void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } int find(int u){ return u==pa[u]?u:pa[u]=find(pa[u]); } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } siz[u]=1; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; dep[v]=dep[u]+1; num[v]=++sont[u]; dfs(v); siz[u]+=siz[v]; if(!son[u]||siz[son[u]]<siz[v]){ son[u]=v; } } } } void dfs(int u,int tp){ dfn[u]=++idx; pos[idx]=u; top[u]=tp; if(son[u]){ dfs(son[u],tp); } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]&&v!=son[u]){ dfs(v,v); } } } void pushdown(int o){ minv[o*2]=min(minv[o*2],tag[o]); minv[o*2+1]=min(minv[o*2+1],tag[o]); tag[o*2]=min(tag[o*2],tag[o]); tag[o*2+1]=min(tag[o*2+1],tag[o]); tag[o]=inf; } void upd(int o,int l,int r,int L,int R,int x){ if(L<=l&&R>=r){ minv[o]=min(minv[o],x); tag[o]=min(tag[o],x); return; } if(tag[o]!=inf){ pushdown(o); } int mid=(l+r)/2; if(L<=mid){ upd(o*2,l,mid,L,R,x); } if(R>mid){ upd(o*2+1,mid+1,r,L,R,x); } minv[o]=min(minv[o*2],minv[o*2+1]); } void update(int u,int v,int x){ while(top[u]!=top[v]){ upd(1,1,n,dfn[top[u]],dfn[u],x); u=fa[top[u]][0]; } upd(1,1,n,dfn[v],dfn[u],x); } void getmin(int o,int l,int r){ if(l==r){ minn[pos[l]]=minv[o]; return; } if(tag[o]!=inf){ pushdown(o); } int mid=(l+r)/2; getmin(o*2,l,mid); getmin(o*2+1,mid+1,r); } void work(edge &e){ int u=e.u,v=e.v,d; d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ u=e.u; d=dep[u]-dep[v]-2; if(d<0){ return; } for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } update(e.u,u,e.d); return; } int tmpu=u,tmpv=v; for(int i=15;i>=0;i--){ if(fa[tmpu][i]!=fa[tmpv][i]){ tmpu=fa[tmpu][i]; tmpv=fa[tmpv][i]; } } link[fa[tmpu][0]].push_back((edge){tmpu,tmpv,e.d}); d=dep[e.u]-dep[tmpu]-1; if(d>=0){ u=e.u; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } update(e.u,u,e.d); } d=dep[e.v]-dep[tmpv]-1; if(d>=0){ v=e.v; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ v=fa[v][i]; } } update(e.v,v,e.d); } } int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++){ scanf("%d%d%d%d",&e[i].u,&e[i].v,&d,&f); e[i].d=d*(1-f); } sort(e+1,e+m+1); ns=0; for(int i=1;i<=m&&ns<n-1;i++){ u=find(e[i].u),v=find(e[i].v); if(u!=v){ use[i]=true; pa[v]=u; ns++; adde(e[i].u,e[i].v); adde(e[i].v,e[i].u); w[e[i].u]+=e[i].d; w[e[i].v]+=e[i].d; smst+=e[i].d; if(!rt){ rt=e[i].u; } } } dfs(rt); dfs(rt,rt); for(int i=1;i<=m;i++){ if(!use[i]){ if(dep[e[i].u]<dep[e[i].v]){ swap(e[i].u,e[i].v); } work(e[i]); } } getmin(1,1,n); for(int i=1;i<=n;i++){ edges.clear(); s=sont[i]; if(fa[i][0]){ s++; for(int j=head[i];j;j=nxt[j]){ v=to[j]; if(v!=fa[i][0]&&minn[v]!=inf){ edges.push_back((edge){num[v],s,minn[v]}); } } } for(int j=0;j<link[i].size();j++){ edges.push_back((edge){num[link[i][j].u],num[link[i][j].v],link[i][j].d}); } sort(edges.begin(),edges.end()); mst=0; for(int j=1;j<=s;j++){ pa[j]=j; } ns=0; for(int j=0;j<edges.size()&&ns<s-1;j++){ u=find(edges[j].u),v=find(edges[j].v); if(u!=v){ pa[v]=u; ns++; mst+=edges[j].d; } } if(ns<s-1){ puts("inf"); }else{ printf("%d\n",smst-w[i]+mst); } } } return 0; }
T2 luogu3379 模板题
#include<cstdio> #include<algorithm> using namespace std; int n,m,root,cnt,u,v,head[500005],to[1000005],nxt[1000005],dep[500005],fa[500005][21]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; dep[v]=dep[u]+1; dfs(v); } } } int lca(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ return u; } for(int i=20;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int main(){ scanf("%d%d%d",&n,&m,&root); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); adde(u,v); adde 19255 (v,u); } dfs(root); while(m--){ scanf("%d%d",&u,&v); printf("%d\n",lca(u,v)); } return 0; }
T3 zoj3195 模板题
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,q,cnt,u,v,d,head[50005],to[100005],nxt[100005],dep[50005],dis[50005],dd[100005],fa[50005][21]; bool flag=false; void adde(int u,int v,int d){ to[++cnt]=v; nxt[cnt]=head[u]; dd[cnt]=d; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; dep[v]=dep[u]+1; dis[v]=dis[u]+dd[i]; dfs(v); } } } int lca(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ return u; } for(int i=20;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int main(){ while(~scanf("%d",&n)){ if(!flag){ flag=true; }else{ puts(""); } cnt=0; memset(head,0,sizeof(head)); memset(dep,0,sizeof(dep)); memset(fa,0,sizeof(fa)); memset(dis,0,sizeof(dis)); for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&d); u++,v++; adde(u,v,d); adde(v,u,d); } dfs(1); scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d%d",&u,&v,&d); u++,v++,d++; printf("%d\n",dis[u]+dis[v]+dis[d]-dis[lca(u,v)]-dis[lca(u,d)]-dis[lca(v,d)]); } } return 0; }
T4 bzoj2588 主席树+树上差分+倍增lca
#include<cstdio> #include<vector> #include<algorithm> using namespace std; const int N=100005; int n,m,x,y,k,lca,lastans=0,tot=0,cnt=0,a ,head ,nxt[N*2],to[N*2],root ,dep ,fa [20]; vector<int> v; struct Node { int l,r,sum; Node(){sum=0;} }node[N*40]; int getId(int x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1; } void adde(int u,int v) { to[++tot]=v; nxt[tot]=head[u]; head[u]=tot; } void update(int l,int r,int &x,int y,int pos) { node[x=++cnt]=node[y]; node[x].sum++; if(l==r) return; int mid=(l+r)/2; if(pos<=mid) update(l,mid,node[x].l,node[y].l,pos); else update(mid+1,r,node[x].r,node[y].r,pos); } int query(int l,int r,int a,int b,int c,int d,int k) { if(l==r) return l; int mid=(l+r)/2,sum=node[node[a].l].sum+node[node.l].sum-node[node[c].l].sum-node[node[d].l].sum; if(k<=sum) return query(l,mid,node[a].l,node[b].l,node[c].l,node[d].l,k); else return query(mid+1,r,node[a].r,node[b].r,node[c].r,node[d].r,k-sum); } void dfs(int pre,int u,int d) { fa[u][0]=pre; dep[u]=d; for(int i=1;(1<<i)<=d;i++) fa[u][i]=fa[fa[u][i-1]][i-1]; update(1,n,root[u],root[pre],getId(a[u])); for(int i=head[u];i;i=nxt[i]) if(to[i]^pre) dfs(u,to[i],d+1); } int LCA(int u,int v) { if(dep[u]>dep[v]) swap(u,v); int d=dep[v]-dep[u]; for(int i=0;(1<<i)<=d;i++) if((1<<i)&d) v=fa[v][i]; if(u!=v) { for(int i=16;i>=0;i--) if(fa[u][i]!=fa[v][i]) { u=fa[u][i]; v=fa[v][i]; } u=fa[u][0]; } return u; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); v.push_back(a[i]); } sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); adde(x,y); adde(y,x); } dfs(0,1,1); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&k); x^=lastans; lca=LCA(x,y); lastans=v[query(1,n,root[x],root[y],root[lca],root[fa[lca][0]],k)-1]; printf("%d",lastans); if(i^m) putchar('\n'); } return 0; }
[b]T5 bzoj1787&&bzoj1832 模版题
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,q,cnt,u,v,d,t1,t2,t3,p,head[500005],to[1000005],nxt[1000005],dep[500005],fa[500005][21]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; dep[v]=dep[u]+1; dfs(v); } } } int lca(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ return u; } for(int i=20;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int dis(int u,int v){ return dep[u]+dep[v]-2*dep[lca(u,v)]; } int main(){ scanf("%d%d",&n,&q); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } dfs(1); for(int i=1;i<=q;i++){ scanf("%d%d%d",&u,&v,&d); t1=lca(u,v),t2=lca(u,d),t3=lca(v,d); if(t1==t2){ p=t3; } else if(t1==t3){ p=t2; } else{ p=t1; } printf("%d %d\n",p,dis(u,p)+dis(v,p)+dis(d,p)); } return 0; }
T6 hdu2586 模版题
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,q,cnt,u,v,d,head[40005],to[80005],nxt[80005],dep[40005],dis[40005],dd[800005],fa[40005][21]; void adde(int u,int v,int d){ to[++cnt]=v; nxt[cnt]=head[u]; dd[cnt]=d; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; dep[v]=dep[u]+1; dis[v]=dis[u]+dd[i]; dfs(v); } } } int lca(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ return u; } for(int i=20;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int main(){ scanf("%d",&t); while(t--){ scanf("%d%d",&n,&q); cnt=0; memset(head,0,sizeof(head)); memset(dep,0,sizeof(dep)); memset(fa,0,sizeof(fa)); memset(dis,0,sizeof(dis)); for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&d); adde(u,v,d); adde(v,u,d); } dfs(1); for(int i=1;i<=q;i++){ scanf("%d%d",&u,&v); printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]); } } return 0; }
T7 poj1330 模版题
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,cnt,u,v,head[10005],to[10005],nxt[10005],dep[10005],fa[10005][21]; bool ck[10005]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; fa[v][0]=u; dep[v]=dep[u]+1; dfs(v); } } int lca(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ return u; } for(int i=20;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int main(){ scanf("%d",&t); while(t--){ scanf("%d",&n); cnt=0; memset(head,0,sizeof(head)); memset(dep,0,sizeof(dep)); memset(fa,0,sizeof(fa)); memset(ck,0,sizeof(ck)); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); adde(u,v); ck[v]=true; } for(int i=1;i<=n;i++){ if(!ck[i]){ dfs(i); break; } } scanf("%d%d",&u,&v); printf("%d\n",lca(u,v)); } return 0; }
T8 gdgzoi2232祖孙询问 模版题
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int t,n,m,cnt,u,v,tmp,rt,head[40005],to[80005],nxt[80005],dep[40005],fa[40005][21]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; dep[v]=dep[u]+1; dfs(v); } } } int lca(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ u=fa[u][i]; } } if(u==v){ return u; } for(int i=20;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ u=fa[u][i]; v=fa[v][i]; } } return fa[u][0]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&u,&v); if(~v){ adde(u,v); adde(v,u); } else{ rt=u; } } dfs(rt); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); tmp=lca(u,v); if(tmp==u){ puts("1"); }else if(tmp==v){ puts("2"); }else{ puts("0"); } } return 0; }
这么多水题忽然好颓废啊!
T9 luogu1967&&xsy2018 倍增+最大生成树
#include<cstdio> #include<algorithm> using namespace std; int n,m,q,u,v,cnt,pa[10005],head[10005],to[20005],nxt[20005],dd[20005],fa[10005][20],minn[10005][20]; int dep[10005]; struct edge{ int u,v,d; }e[50005]; bool cmp(edge a,edge b){ return a.d>b.d; } int find(int u){ return u==pa[u]?u:pa[u]=find(pa[u]); } void adde(int u,int v,int d){ to[++cnt]=v; nxt[cnt]=head[u]; dd[cnt]=d; head[u]=cnt; } void dfs(int u){ for(int i=1;(1<<i)<=dep[u];i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; minn[u][i]=min(minn[u][i-1],minn[fa[u][i-1]][i-1]); } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][0]){ fa[v][0]=u; minn[v][0]=dd[i]; dep[v]=dep[u]+1; dfs(v); } } } int solve(int u,int v){ if(dep[u]<dep[v]){ swap(u,v); } int ans=0x7fffffff,d=dep[u]-dep[v]; for(int i=0;(1<<i)<=d;i++){ if(d&(1<<i)){ ans=min(ans,minn[u][i]); u=fa[u][i]; } } if(u==v){ return ans; } for(int i=16;i>=0;i--){ if(fa[u][i]!=fa[v][i]){ ans=min(ans,min(minn[u][i],minn[v][i])); u=fa[u][i]; v=fa[v][i]; } } if(fa[u][0]){ return min(ans,min(minn[u][0],minn[v][0])); }else{ return -1; } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ pa[i]=i; } for(int i=1;i<=m;i++){ scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].d); } sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++){ u=find(e[i].u),v=find(e[i].v); if(u!=v){ adde(e[i].u,e[i].v,e[i].d); adde(e[i].v,e[i].u,e[i].d); pa[v]=u; } } dfs(1); scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d",&u,&v); printf("%d\n",solve(u,v)); } return 0; }
T10 CF587C&&xsy2414 倍增+归并
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,q,u,v,t,tmp,cnt,ans[15],a[100005],head[100005],to[200005],nxt[200005],fa[100005][20],dep[100005],minn[100005][20][15]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void merge(int a[],int b[],int d[]){ int i=1,j=1,k=0,c[15]; while(i<=a[0]&&j<=b[0]&&k<10){ if(a[i]<b[j]){ c[++k]=a[i++]; }else{ c[++k]=b[j++]; } } while(i<=a[0]&&k<10){ c[++k]=a[i++]; } while(j<=b[0]&&k<10){ c[++k]=b[j++]; } for(int i=1;i<=k;i++){ d[i]=c[i]; } d[0]=k; } void dfs(int u){ memcpy(minn[u][1],minn[fa[u][1]][0],sizeof(minn[fa[u][1]][0])); for(int i=2;i<=17;i++){ fa[u][i]=fa[fa[u][i-1]][i-1]; merge(minn[u][i-1],minn[fa[u][i-1]][i-1],minn[u][i]); } int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u][1]){ fa[v][1]=u; dep[v]=dep[u]+1; dfs(v); } } } void solve(int u,int v,int t){ if(dep[u]<dep[v]){ swap(u,v); } int d=dep[u]-dep[v]; memcpy(ans,minn[u][0],sizeof(minn[u][0])); for(int i=1;i<=17;i++){ if(d&(1<<(i-1))){ merge(ans,minn[u][i],ans); u=fa[u][i]; } } if(u!=v){ merge(ans,minn[v][0],ans); for(int i=17;i>=1;i--){ if(fa[u][i]!=fa[v][i]){ merge(ans,minn[u][i],ans); merge(ans,minn[v][i],ans); u=fa[u][i]; v=fa[v][i]; } } merge(ans,minn[u][1],ans); } ans[0]=min(ans[0],t); printf("%d ",ans[0]); for(int i=1;i<=ans[0];i++){ printf("%d ",ans[i]); } puts(""); } int main(){ scanf("%d%d%d",&n,&m,&q); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } for(int i=1;i<=m;i++){ scanf("%d",&tmp); minn[tmp][0][++minn[tmp][0][0]]=i; } dfs(1); for(int i=1;i<=q;i++){ scanf("%d%d%d",&u,&v,&t); solve(u,v,t); } return 0; }
T11 bzoj3545&&bzoj3551 并查集+谜之建树+倍增+线段树
#include<cstdio> #include<algorithm> #include<vector> using namespace std; inline int rd() { int x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int N=100005; int n,m,q,tot,cnt,idx,h ,pa[2*N],val[2*N],head[N*2],to[N*2],nxt[N*2],dep[N*2],fa[N*2][20],mx[N*2][20]; int lc[50*N],rc[50*N],sumv[50*N],pos[N*3],root[N*3],bg[N*2],ed[N*2]; bool vis[N*2]; vector<int> V; struct edge { int u,v,d; }a[5*N]; bool cmp(edge a,edge b) { return a.d<b.d; } int findrt(int u) { return u==pa[u]?u:pa[u]=findrt(pa[u]); } void adde(int u,int v) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int u) { vis[u]=true; pos[++pos[0]]=u; for(int i=1;(1<<i)<=dep[u];i++) { fa[u][i]=fa[fa[u][i-1]][i-1]; mx[u][i]=max(mx[u][i-1],mx[fa[u][i-1]][i-1]); } for(int i=head[u];i;i=nxt[i]) { dep[to[i]]=dep[u]+1; fa[to[i]][0]=u; mx[to[i]][0]=val[u]; dfs(to[i]); } if(u>n) pos[++pos[0]]=u; } void update(int &x,int y,int l,int r,int k) { x=++idx; sumv[x]=sumv[y]+1; lc[x]=lc[y]; rc[x]=rc[y]; if(l==r) return; int mid=(l+r)/2; if(k<=mid) update(lc[x],lc[y],l,mid,k); else update(rc[x],rc[y],mid+1,r,k); } int query(int x,int y,int l,int r,int k) { if(l==r) return l; int mid=(l+r)/2,sum=sumv[lc[y]]-sumv[lc[x]]; if(k<=sum) return query(lc[x],lc[y],l,mid,k); else return query(rc[x],rc[y],mid+1,r,k-sum); } void build() { tot=n; sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { int p=findrt(a[i].u),q=findrt(a[i].v); if(p^q) { tot++; pa[p]=pa[q]=tot; val[tot]=a[i].d; adde(tot,p); adde(tot,q); if(tot==n*2-1) break; } } for(int i=1;i<=n;i++) if(!vis[i]) dfs(findrt(i)); for(int i=1;i<=pos[0];i++) { int tmp=pos[i]; if(tmp<=n) update(root[i],root[i-1],1,n,h[tmp]); else { root[i]=root[i-1]; if(!bg[tmp]) bg[tmp]=i; else ed[tmp]=i; } } } int find(int x,int v) { for(int i=17;i>=0;i--) if(dep[x]>=(1<<i)&&mx[x][i]<=v) x=fa[x][i]; return x; } void solve() { int ans=0,v,x,k; for(int i=1;i<=q;i++) { v=rd(),x=rd(),k=rd(); if(ans!=-1) v^=ans,x^=ans,k^=ans; int t=find(v,x); int a=root[bg[t]],b=root[ed[t]]; if(sumv[b]-sumv[a]<k) ans=-1; else ans=V[query(a,b,1,n,sumv[b]-sumv[a]-k+1)-1]; printf("%d\n",ans); } } int main() { n=rd(),m=rd(),q=rd(); for(int i=1;i<=n;i++) V.push_back(h[i]=rd()); sort(V.begin(),V.end()); for(int i=1;i<=n;i++) h[i]=lower_bound(V.begin(),V.end(),h[i])-V.begin()+1; for(int i=1;i<=2*n;i++) pa[i]=i; for(int i=1;i<=m;i++) a[i].u=rd(),a[i].v=rd(),a[i].d=rd(); build(); solve(); return 0; }
终于写完了,好嗨森!
相关文章推荐
- LCA和RMQ题目汇总
- LCA和RMQ题目汇总
- 【Learning】Link-Cut Tree 题目汇总
- 【Learning】动态树分治题目汇总
- 【learning】树形dp题目汇总
- [省选前题目整理][POJ 1330]Nearest Common Ancestors(倍增法求LCA)
- 【Learning】虚树题目汇总
- Java笔试题目汇总___选择题
- C/C++ 笔试、面试题目大汇总
- IT面试题目汇总
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
- 模板 树上求LCA 倍增和树链剖分
- 洛谷 P2633 Count on a tree[bzoj2588](倍增lca+主席树)
- 嵌入式工程师笔试题目汇总
- C++题目汇总
- 面试类链表题目汇总
- 大型公司笔试题目汇总(2)——网易计算机类笔试题目
- java面试汇总(总结了所有的面试中可能出现的题目)
- bzoj 4539 hnoi2016 树 倍增lca+主席树
- [Contest] Cqoi2016 题目汇总