BZOJ 3545/BZOJ 3551 Peaks

Posted on 2016-09-18 14:27  ziliuziliu  阅读(174)  评论(0编辑  收藏  举报

kruskal重构树。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxv 200050
#define maxe 2000050
#define inf 2147483647
using namespace std;
struct edges
{
    int u,v,w;
}es[maxe];
struct edge
{
    int v,nxt;
}e[maxe];
int n,m,q,h[maxv],hash[maxv],x,y,z,lastans=0,val[maxv],g[maxv],nume=0,father[maxv];
int dis[maxv],l[maxv],r[maxv],fdfn[maxv],anc[maxv][21],times=0;
int root[maxv],tot=0,tots=0,ls[maxv*23],rs[maxv*23],sum[maxv*23],len;
bool cmp(edges x,edges y)
{
    return x.w<y.w;
}
int read()
{
    char ch;int data=0;
    while (ch<'0' || ch>'9') ch=getchar();
    while (ch>='0' && ch<='9')
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data;
}
void addedge(int u,int v)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    g[u]=nume;
}
int getfather(int x)
{
    if (father[x]!=x) father[x]=getfather(father[x]);
    return father[x];
}
void kruskal_tree()
{
    sort(es+1,es+m+1,cmp);
    for (int i=1;i<=2*n;i++) father[i]=i;
    for (int i=1;i<=m;i++)
    {
        int u=es[i].u,v=es[i].v,w=es[i].w;
        int f1=getfather(es[i].u),f2=getfather(es[i].v);
        if (f1!=f2)
        {
            tot++;
            father[f1]=tot;father[f2]=tot;val[tot]=es[i].w;
            addedge(f1,tot);addedge(tot,f1);addedge(f2,tot);addedge(tot,f2);
        }
    }
}
void dfs(int x)
{
    int flag=0;l[x]=inf;r[x]=0;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if (anc[x][0]!=v)
        {
            flag=1;
            anc[v][0]=x;dis[v]=dis[x]+1;
            dfs(v);
            l[x]=min(l[x],l[v]);r[x]=max(r[x],r[v]);
        }
    }
    if (!flag)
    {
        l[x]=r[x]=++times;
        fdfn[times]=x;
    }
}
void get_table()
{
    for (int e=1;e<=20;e++)
        for (int i=1;i<=tot;i++)
            anc[i][e]=anc[anc[i][e-1]][e-1];
}
int bnd(int x)
{
    return lower_bound(hash+1,hash+len+1,x)-hash;
}
void insert(int last,int &now,int left,int right,int pos)
{
    now=++tots;sum[now]=sum[last]+1;
    if (left==right) return;
    ls[now]=ls[last];rs[now]=rs[last];
    int mid=left+right>>1;
    if (pos<=mid) insert(ls[last],ls[now],left,mid,pos);
    else insert(rs[last],rs[now],mid+1,right,pos);
}
void build_seg()
{
    sort(hash+1,hash+n+1);
    len=unique(hash+1,hash+n+1)-hash-1;
    for (int i=1;i<=n;i++)
        insert(root[i-1],root[i],1,len,bnd(h[fdfn[i]]));
}
int find(int x,int k)
{
    for (int e=20;e>=0;e--)
    {
        if ((val[anc[x][e]]<=k) && (anc[x][e]))
            x=anc[x][e];
    }
    return x;
}
int ask(int last,int now,int left,int right,int k)
{
    if (left==right) return hash[left];
    int mid=left+right>>1;
    int r=sum[rs[now]]-sum[rs[last]];
    if (r>=k) return ask(rs[last],rs[now],mid+1,right,k);
    else return ask(ls[last],ls[now],left,mid,k-r);
}
void work()
{
    x=read();y=read();z=read();
    x^=lastans;y^=lastans;z^=lastans;
    int k=find(x,y);
    if (r[k]-l[k]+1<z) {printf("-1\n");lastans=0;}
    else 
    {
        lastans=ask(root[l[k]-1],root[r[k]],1,len,z);
        printf("%d\n",lastans);
    }
}
int main()
{
    n=read();m=read();q=read();tot=n;
    for (int i=1;i<=n;i++) {h[i]=read();hash[i]=h[i];}
    for (int i=1;i<=m;i++) {es[i].u=read();es[i].v=read();es[i].w=read();}
    kruskal_tree();
    dfs(tot);
    get_table();
    build_seg();
    for (int i=1;i<=q;i++)
        work();
    return 0;
}