[BZOJ3551]Peaks加强版
题目大意:见https://www.cnblogs.com/Mrsrz/p/9354136.html
强制在线
解题思路:
Kruskal重构树。
我们从小到大加入边,每次合并两个连通块时,新建一个节点作为它们的父亲,点权为原来的边权。
然后对于每个询问,倍增找最上方的点权不超过x的点,则该点构成的子树上的所有叶子节点就是原来的点能到的所有节点。
于是对每棵子树建主席树,查询时就是在子树内查询第k大。建主席树时相当于线段树合并。
C++ Code:
#include<bits/stdc++.h> #define N 100005 template<typename T> inline void read(T&d){ d=0;static int c; for(c=getchar();!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); } struct edge{ int u,v,dis; inline bool operator<(const edge&rhs)const{return dis<rhs.dis;} }E[N*5]; struct Edge{ int to,nxt; }e[N<<3]; struct segmentTreeNode{ int s,ls,rs; }d[6000005]; int n,m,q,h[N],fa[N<<1],nodes,f[N<<1][19],cnt=0,dang[N<<1],head[N<<1],hh[N],rt[N<<1]; int treenode=0; inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void init(int l,int r,int&o,int p){ o=++treenode; d[o].s=1; if(l==r)return; int mid=l+r>>1; if(p<=mid)init(l,mid,d[o].ls,p);else init(mid+1,r,d[o].rs,p); } int merge(int ls,int rs){ if(!ls||!rs)return ls|rs; int nw=++treenode; if(!d[ls].ls&&!d[ls].rs){ d[nw].s=d[ls].s+d[rs].s; return nw; } d[nw].ls=merge(d[ls].ls,d[rs].ls); d[nw].rs=merge(d[ls].rs,d[rs].rs); d[nw].s=d[d[nw].ls].s+d[d[nw].rs].s; return nw; } void dfs(int now){ for(int i=head[now];i;i=e[i].nxt){ dfs(e[i].to); if(!rt[now])rt[now]=rt[e[i].to];else rt[now]=merge(rt[now],rt[e[i].to]); } if(!head[now]) init(0,N,rt[now],hh[now]); } int query(int l,int r,int&o,int k){ if(l==r)return l; int mid=l+r>>1; if(d[d[o].rs].s>=k)return query(mid+1,r,d[o].rs,k); return query(l,mid,d[o].ls,k-d[d[o].rs].s); } int main(){ read(n),read(m),read(q); for(int i=1;i<=n;++i)read(h[i]),hh[i]=h[i]; std::sort(h+1,h+n+1); int nn=std::unique(h+1,h+n+1)-h-1; for(int i=1;i<=n;++i)hh[i]=std::lower_bound(h+1,h+nn+1,hh[i])-h; for(int i=1;i<=m;++i)read(E[i].u),read(E[i].v),read(E[i].dis); std::sort(E+1,E+m+1); for(int i=1;i<=n;++i)fa[i]=i,fa[i+n]=i+n; nodes=n; for(int less_node=n-1,i=1;less_node&&i<=m;++i){ int x=find(E[i].u),y=find(E[i].v); if(x!=y){ fa[x]=fa[y]=f[x][0]=f[y][0]=++nodes; dang[nodes]=E[i].dis; --less_node; e[++cnt]=(Edge){x,head[nodes]}; head[nodes]=cnt; e[++cnt]=(Edge){y,head[nodes]}; head[nodes]=cnt; } } dang[0]=0x3f3f3f3f; memset(d,0,sizeof d); dfs(nodes); for(int j=1;j<19;++j) for(int i=1;i<=nodes;++i) f[i][j]=f[f[i][j-1]][j-1]; int ans=0; while(q--){ int u,x,k; read(u),read(x),read(k); u^=ans,x^=ans,k^=ans; for(int i=18;~i;--i)if(dang[f[u][i]]<=x)u=f[u][i]; if(d[rt[u]].s<k)puts("-1"),ans=0;else printf("%d\n",ans=h[query(0,N,rt[u],k)]); } return 0; }