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

 

posted @ 2019-02-15 08:49  寒雨微凝  阅读(146)  评论(0编辑  收藏  举报