BZOJ3551 Peaks加强版
kruskal重构树模板题
简单介绍kruskal重构树
就是对于原先的kruskal最小生成树算法进行扩展 每一次加入一条边就新建一个点并且将原先并查集合并即连边
最后形成的树形图是所有原先存在的点都位于叶子 而新加的点即对应的边位于上方 这样的话就可以通过倍增来限制树上走过的边
对于此题来说 我们需要询问静态子树第k大 那么就是显然的主席树上树问题 由于强制在线所以貌似kruskal重构树是比较好的办法
注意数组别开太大 容易M qaq 然后BZ给我显示的T 我也是很郁闷qaq
//Love and Freedom. #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define inf 20021225 #define ll long long #define M 500010 #define N 200010 using namespace std; struct edge{int u,v,w;}e[M]; struct _edge{int to,lt;}t[N<<1]; int bel[N<<1],val[N<<1],id[N<<1],dfn[N<<1],cnt,in[N<<1],poi; void add(int x,int y,int v,int id){e[id].u=x;e[id].v=y;e[id].w=v;} void _add(int x,int y){t[++cnt].to=y; t[cnt].lt=in[x]; in[x]=cnt;} struct node{int ls,rs,s;}; int n,m,q,nn; int read() { char ch; int s=0; ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s; } struct sgt { node t[N*20];int rt[N<<1],poi; void pushup(int x){t[x].s=t[t[x].ls].s+t[t[x].rs].s;} void build(int &x,int l,int r) { if(l==r) return; int mid=l+r>>1; build(t[x].ls,l,mid); build(t[x].rs,mid+1,r); } void insert(int &x,int lt,int l,int r,int d) { x = ++poi; t[x] = t[lt]; if(l==r){t[x].s++;return;} int mid=l+r>>1; if(d<=mid) insert(t[x].ls,t[lt].ls,l,mid,d); else insert(t[x].rs,t[lt].rs,mid+1,r,d); pushup(x); } int query(int x,int y,int l,int r,int d) { if(l==r) return l; int s=t[t[y].rs].s-t[t[x].rs].s,mid=l+r>>1;; if(s>=d) return query(t[x].rs,t[y].rs,mid+1,r,d); else return query(t[x].ls,t[y].ls,l,mid,d-s); } }sgt; int find(int x) { if(!bel[x]) return x; return bel[x]=find(bel[x]); } bool cmp(edge a,edge b){return a.w<b.w;} void kruskal() { sort(e+1,e+m+1,cmp); poi=n; for(int i=1;i<=m;i++) { int x=e[i].u,y=e[i].v; int fx=find(x),fy=find(y); if(fx!=fy) { val[++poi]=e[i].w; _add(poi,fx); _add(poi,fy); bel[fx]=poi; bel[fy]=poi; if(poi == 2*n-1) break; } } } int f[N<<1][18],idx,ed[N<<1]; void dfs(int x) { for(int i=1;i<18;i++) f[x][i]=f[f[x][i-1]][i-1]; dfn[x]=++idx; id[idx]=x; if(x<=n) sgt.insert(sgt.rt[idx],sgt.rt[idx-1],1,nn,val[x]); else sgt.rt[idx]=sgt.rt[idx-1]; for(int i=in[x];i;i=t[i].lt) { int y=t[i].to;// if(dfn[y]) continue; f[y][0]=x; dfs(y); } ed[x]=idx; } int find_pos(int x,int w) { for(int i=17;~i;i--) if(val[f[x][i]]<=w) x=f[x][i]; return x; }int h[N],r[N]; int main() { n=read();m=read();q=read(); val[0]=inf*100; for(int i=1;i<=n;i++) h[i]=read(),r[i]=h[i]; sort(r+1,r+n+1);nn=unique(r+1,r+n+1)-r-1; for(int i=1;i<=n;i++) val[i]=lower_bound(r+1,r+nn+1,h[i])-r; int x,y,w,k,lastans=0; for(int i=1;i<=m;i++) { x=read(),y=read(),w=read(); add(x,y,w,i); } kruskal(); sgt.build(sgt.rt[0],1,nn); for(int i=1;i<=n;i++) if(!dfn[i]) dfs(find(i)); for(int i=1;i<=q;i++) { x=read();y=read();k=read(); x^=lastans; y^=lastans; k^=lastans; x=find_pos(x,y); if(sgt.t[sgt.rt[ed[x]]].s-sgt.t[sgt.rt[dfn[x]]].s<k) printf("%d\n",lastans=-1); else printf("%d\n",lastans=r[sgt.query(sgt.rt[dfn[x]],sgt.rt[ed[x]],1,nn,k)]); if(lastans==-1) lastans=0; } return 0; }