【ONTAK2010】【BZOJ3551】Peaks加强版

Description

【题目描述】同3545
Input

第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。
Output

同3545
Sample Input

Sample Output

HINT

【数据范围】同3545
Source

不强制在线肯定会,平衡树启发式合并一下就行了
至于强制在线..
黄学长的题解

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100010
#define SIZE 5000010
#define LL long long
#define GET (ch>='0'&&ch<='9')
using namespace std;
inline void in(int &x)
{
    char ch=getchar();x=0;int flag=1;
    while (!GET)    flag=ch=='-'?-1:1,ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();x*=flag;
}
int n,m,q,cnt,top,lastans;
int Pow[20],h[MAXN],que[MAXN];
int f[MAXN<<1];
int sta[MAXN<<2],tp,In[MAXN<<1],Out[MAXN<<1];
int deep[MAXN<<1],val[MAXN<<1],fa[MAXN<<1][20],maxn[MAXN<<1][20];
int root[MAXN<<2],ls[SIZE],rs[SIZE],sz[SIZE];
bool vis[MAXN<<1];
inline int find(int x)  {   return f[x]==x?x:f[x]=find(f[x]);   }
struct edge {   int to; edge *next; }e[MAXN<<1],*prev[MAXN<<1];
inline void insert(int u,int v) {   e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];  }
struct Edge
{   
    int u,v,w;
    inline bool operator <(const Edge& a)const  {   return w<a.w;   }
}s[MAXN*5];
void ins(int x,int &y,int l,int r,int val)
{
    sz[y=++cnt]=sz[x]+1;
    ls[y]=ls[x];rs[y]=rs[x];
    if (l==r)   return;
    int mid=(l+r)>>1;
    if (val<=mid)   ins(ls[x],ls[y],l,mid,val);
    else    ins(rs[x],rs[y],mid+1,r,val);
}
int query(int x,int y,int l,int r,int k)
{
    if (l==r)   return l;
    int mid=(l+r)>>1;
    if (sz[ls[y]]-sz[ls[x]]>=k) return query(ls[x],ls[y],l,mid,k);
    else    return query(rs[x],rs[y],mid+1,r,k-sz[ls[y]]+sz[ls[x]]);
}
void dfs(int x)
{
    vis[x]=1;sta[++tp]=x;
    for (int i=1;i<=16;i++)
        if (deep[x]>=Pow[i])    fa[x][i]=fa[fa[x][i-1]][i-1],maxn[x][i]=max(maxn[x][i-1],maxn[fa[x][i-1]][i-1]);
        else    break;
    for (edge *i=prev[x];i;i=i->next)
        deep[i->to]=deep[x]+1,maxn[i->to][0]=val[x],fa[i->to][0]=x,dfs(i->to);
    if (x>n)    sta[++tp]=x;
}
inline int get_f(int x,int val)
{
    for (int i=17;i>=0;i--) if (deep[x]>=Pow[i]&&maxn[x][i]<=val)   x=fa[x][i];
    return x;
}
int main()
{
    for (int i=0;i<20;i++)  Pow[i]=(1<<i);
    in(n);in(m);in(q);
    int tot=n,v,x,k,t;
    for (int i=1;i<=n;i++)  in(h[i]),que[i]=h[i];
    sort(que+1,que+n+1);//t=unique(que+1,que+n+1)-que;
    for (int i=1;i<=n;i++)  h[i]=lower_bound(que+1,que+n+1,h[i])-que;
    for (int i=1;i<=(n<<1);i++) f[i]=i;
    for (int i=1;i<=m;i++)  in(s[i].u),in(s[i].v),in(s[i].w);
    sort(s+1,s+m+1);
    for (int i=1;i<=m;i++)
    {
        int x=find(s[i].u),y=find(s[i].v);
        if (x!=y)
        {
            tot++;f[x]=f[y]=tot;val[tot]=s[i].w;
            insert(tot,x);insert(tot,y);
            if (tot==(n<<1)-1)  break;
        }
    }
    for (int i=1;i<=n;i++)  if (!vis[i])    dfs(find(i));
    for (int i=1;i<=tp;i++)
    {
        int t=sta[i];
        if (t<=n)   ins(root[i-1],root[i],1,n,h[t]);
        else
        {
            root[i]=root[i-1];
            if (!In[t]) In[t]=i;    else    Out[t]=i;
        }
    }
    while (q--)
    {
        in(v);in(x);in(k);
        if (lastans!=-1)    v^=lastans,x^=lastans,k^=lastans;
        int t=get_f(v,x),a=root[In[t]],b=root[Out[t]];
        if (sz[b]-sz[a]<k)  lastans=-1;
        else    lastans=que[query(a,b,1,n,sz[b]-sz[a]-k+1)];
        printf("%d\n",lastans);
    }
}

你可能感兴趣的:(dfs序,主席树,倍增)