n<=100000,m<=500000的图有点权边权,q<=500000个询问每次问从x出发经过不超过y的边权能到的点权第K大,加强版强制在线。
Emmmmmm有一个漂亮的方法来转化,就是对原图做MST,做的时候要连接两个点时不要直接连,新开一个点然后让这两个点连上这个点。
这样就把边权挂到树上了,新建的点的点权代表对应的边权,由于是从小到大加边,建成的树上下面的“新建点”的点权一定小于上面的“新建点”的点权,每次回答询问在树上倍增找到点权不超过y的祖先,然后就查询这个祖先的子树内的叶子点的第K大,dfs序+主席树即可。
然后有个小问题,图不一定联通。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<stdlib.h> 5 //#include<iostream> 6 using namespace std; 7 8 int n,m,q; 9 #define maxn 200011 10 #define maxm 2000011 11 struct Point 12 { 13 int from,to,v; 14 bool operator < (const Point &b) const {return v<b.v;} 15 }p[maxm]; 16 17 int ufs[maxn]; 18 void ufsclear(int n) {for (int i=1;i<=n;i++) ufs[i]=i;} 19 int find(int x) {return x==ufs[x]?x:(ufs[x]=find(ufs[x]));} 20 void Union(int x,int y) {x=find(x),y=find(y);if (x==y) return;ufs[x]=y;} 21 struct SMT 22 { 23 struct Node 24 { 25 int son[2]; 26 int cnt; 27 }a[maxm]; 28 int size,n; 29 void clear(int m) {n=m;size=0;a[0].cnt=0;} 30 void insert(int pre,int &rt,int L,int R,int num) 31 { 32 rt=++size; 33 a[rt].cnt=a[pre].cnt+1; 34 if (L==R) {a[rt].son[0]=a[rt].son[1]=0;return;} 35 const int mid=(L+R)>>1; 36 if (num<=mid) insert(a[pre].son[0],a[rt].son[0],L,mid,num),a[rt].son[1]=a[pre].son[1]; 37 else insert(a[pre].son[1],a[rt].son[1],mid+1,R,num),a[rt].son[0]=a[pre].son[0]; 38 } 39 void insert(int pre,int &rt,int num) {insert(pre,rt,1,n,num);} 40 }smt; 41 42 struct Edge{int to,next;}edge[maxn<<1];int first[maxn],le=2; 43 void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;} 44 45 int val[maxn],fa[maxn][20],lisan[maxn],li=0,dep[maxn],ll[maxn],list[maxn],rr[maxn],Time=0; 46 void dfs(int x) 47 { 48 ll[x]=Time+1; 49 for (int i=first[x];i;i=edge[i].next) 50 { 51 const Edge &e=edge[i]; 52 dep[e.to]=dep[x]+1; 53 dfs(e.to); 54 } 55 if (!first[x]) list[++Time]=x; 56 rr[x]=Time; 57 } 58 59 int lca(int x,int y) 60 { 61 if (dep[x]<dep[y]) {int t=x;x=y;y=t;} 62 for (int i=18;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; 63 if (x==y) return x; 64 for (int i=18;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 65 return fa[x][0]; 66 } 67 68 int rt[maxn]; 69 int main() 70 { 71 scanf("%d%d%d",&n,&m,&q); 72 for (int i=1;i<=n;i++) scanf("%d",&val[i]),lisan[++li]=val[i]; 73 sort(lisan+1,lisan+1+n);li=unique(lisan+1,lisan+1+li)-lisan-1; 74 for (int i=1;i<=n;i++) val[i]=lower_bound(lisan+1,lisan+1+li,val[i])-lisan; 75 76 for (int i=1;i<=m;i++) scanf("%d%d%d",&p[i].from,&p[i].to,&p[i].v); 77 sort(p+1,p+1+m); 78 ufsclear(n+n); 79 for (int i=1,cnt=1;i<=m;i++) 80 { 81 int x=find(p[i].from),y=find(p[i].to); 82 if (x==y) continue; 83 int now=n+cnt; val[now]=p[i].v; 84 Union(x,now); Union(y,now); 85 in(now,x); in(now,y); 86 fa[x][0]=now;fa[y][0]=now; 87 cnt++; if (cnt==n) break; 88 } 89 int tot=n+n-1; 90 for (int j=1;j<=18;j++) 91 for (int i=1;i<=tot;i++) 92 fa[i][j]=fa[fa[i][j-1]][j-1]; 93 dep[tot]=1; 94 for (int i=1;i<=tot;i++) if (!fa[i][0]) dfs(i); 95 96 smt.clear(li); 97 for (int i=1;i<=n;i++) smt.insert(rt[list[i-1]],rt[list[i]],val[list[i]]); 98 int last=-1; 99 for (int i=1,x,y,K;i<=q;i++) 100 { 101 scanf("%d%d%d",&x,&y,&K); 102 if (last>=0) x^=last,y^=last,K^=last; 103 int num=val[x],t=x; 104 for (int j=18;j>=0;j--) if (fa[t][j] && val[fa[t][j]]<=y) t=fa[t][j]; 105 // cout<<t<<endl; 106 int u=rt[list[ll[t]-1]],v=rt[list[rr[t]]],L=1,R=li,tmp; 107 if (smt.a[v].cnt-smt.a[u].cnt<K) {printf("%d ",(last=-1));continue;} 108 while (L<R) 109 { 110 const int mid=(L+R)>>1; 111 if ((tmp=smt.a[smt.a[v].son[1]].cnt-smt.a[smt.a[u].son[1]].cnt)>=K) 112 v=smt.a[v].son[1],u=smt.a[u].son[1],L=mid+1; 113 else v=smt.a[v].son[0],u=smt.a[u].son[0],K-=tmp,R=mid; 114 } 115 printf("%d ",(last=lisan[L])); 116 } 117 return 0; 118 }