bzoj 3551 kruskal重构树dfs序上的主席树

强制在线

kruskal重构树,每两点间的最大边权即为其lca的点权。

倍增找,dfs序对应区间搞主席树

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define N 100005
#define M 500005
using namespace std;
 
int l[2*N],r[2*N],cnt,num_cnt,val[2*N],num[2*N],ans;
int sum[25*N],lon[25*N],ron[25*N];
int be[2*N],fa[2*N][21],dis[2*N][21],n,m,q,sz,oo,root[2*N];
int e=1,head[2*N];
bool vis[2*N];
struct edge{
    int u,v,w,next;
}ed[M],a[M];
bool cmp1(edge a,edge b){return a.w<b.w;}
 
void add(int u,int v,int w){
    ed[e].u=u; ed[e].v=v; ed[e].w=w;
    ed[e].next=head[u]; head[u]=e++;
}
int find(int x){
    if(x==be[x])return x;
    be[x]=find(be[x]);
    return be[x];
}
void Kruskal(){
    sort(a+1,a+m+1,cmp1);
    for(int i=1;i<=m;++i){
        int u=a[i].u,v=a[i].v;
        u=find(u); v=find(v);
        if(u!=v){
            be[u]=be[v]=++n;
            fa[u][0]=fa[v][0]=n;
            dis[u][0]=dis[v][0]=a[i].w;
            add(n,u,a[i].w); add(n,v,a[i].w);
        }
    }
}
void insert(int p,int &rt,int l,int r,int x){
    rt=++sz;
    sum[rt]=sum[p]+1;
    if(l==r) return;
    lon[rt]=lon[p]; ron[rt]=ron[p];
    int mid=(l+r)>>1;
    if(x<=mid) insert(lon[p],lon[rt],l,mid,x);
    else insert(ron[p],ron[rt],mid+1,r,x);
}
void dfs(int x){
	for(int i=1;i<=20;i++){
        fa[x][i]=fa[fa[x][i-1]][i-1];
        dis[x][i]=max(dis[x][i-1],dis[fa[x][i-1]][i-1]);
    }
    l[x]=++cnt; 
    if(x<=oo) insert(root[cnt-1],root[cnt],1,num_cnt,val[x]);
    else root[cnt]=root[cnt-1];
    for(int i=head[x];i;i=ed[i].next)
           dfs(ed[i].v);
    r[x]=cnt;
}
int query(int L,int R,int k){
    L=root[L]; R=root[R];
    if(k>sum[R]-sum[L]) return -1;
    int x=1,y=num_cnt;
    while(x<y){
        int mid=(x+y)>>1;
        int tmp=sum[ron[R]]-sum[ron[L]];
        if(tmp>=k){x=mid+1;L=ron[L];R=ron[R];}
        else{k-=tmp;y=mid;L=lon[L];R=lon[R];}
    }
    return num[x];
}
void print(int x,int l,int r){
    if(!x) return;
    printf("x==%d  l==%d  r==%d  sum==%d\n",x,l,r,sum[x]);
    int mid=(l+r)>>1;
    print(lon[x],l,mid);
    print(ron[x],mid+1,r);
}
int main()
{
	//freopen("3545.in","r",stdin);
	//freopen("3545.out","w",stdout);
    int u,v,w,x,k;
    scanf("%d%d%d",&n,&m,&q); oo=n;
    for(int i=1;i<=n;i++){
        scanf("%d",&val[i]);
        num[i]=val[i];
    }
    sort(num+1,num+n+1);
    num_cnt=unique(num+1,num+n+1)-num-1;
    for(int i=1;i<=n;i++)
        val[i]=lower_bound(num+1,num+num_cnt+1,val[i])-num;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
    for(int i=1;i<=2*n;++i)be[i]=i;
    Kruskal();
    memset(vis,0,sizeof vis);
    for(int i=n;i>=1;--i)if(!l[i])dfs(i);
    while(q--){
        scanf("%d%d%d",&v,&x,&k);
        if(ans!=-1){v^=ans;x^=ans;k^=ans;}
        for(int i=20;~i;i--)
            if(dis[v][i]<=x&&fa[v][i])
                v=fa[v][i];
        ans=query(l[v]-1,r[v],k);
        printf("%d\n",ans);
    }
    return 0;
}


posted @ 2017-08-05 08:36  Ren_Ivan  阅读(140)  评论(0编辑  收藏  举报