您的位置:首页 > 其它

【Learning】倍增求LCA题目汇总

2017-12-02 08:18 148 查看
这里是我倍增的练习记录,大多都是水题……也有一些混合了其它算法的。= = silly……顺序可能有些错乱,并不是按照难度来排的。

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;
}


终于写完了,好嗨森!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: