bzoj 2588 Spoj 10628 Count on a tree 树链剖分 主席树

来源:互联网 发布:java判断是否数字 编辑:程序博客网 时间:2024/06/05 19:08

主席树维护树链剖分裸题。
最后换行会PE。。。

#include <bits/stdc++.h>using namespace std;#define N 110000#define M 7100000#define ll long longint n,m,tot,num,cnt,ans;int a[N],b[N],head[N],nex[N<<1],to[N<<1];int fa[N],size[N],son[N],top[N],deep[N],pos[N],val[N];int root[N],ch[M][2],sum[M];int st1[110],st2[110],top1,top2;void add(int x,int y){    tot++;    nex[tot]=head[x];head[x]=tot;    to[tot]=y;}void dfs(int x,int y){    size[x]=1;    fa[x]=y;deep[x]=deep[y]+1;    for(int i=head[x];i;i=nex[i])        if(to[i]!=y)        {            dfs(to[i],x);            size[x]+=size[to[i]];            son[x]=size[to[i]]>size[son[x]] ? to[i]:son[x];        }}void dfs1(int x,int y,int tp){    top[x]=tp;    pos[x]=++num;val[num]=a[x];    if(son[x])dfs1(son[x],x,tp);    for(int i=head[x];i;i=nex[i])        if(to[i]!=y&&to[i]!=son[x])            dfs1(to[i],x,to[i]);}void build(int l,int r,int pre,int &now,int v){    sum[now=++cnt]=sum[pre]+1;    if(l==r)return;    int mid=(l+r)>>1;    ch[now][0]=ch[pre][0];    ch[now][1]=ch[pre][1];    if(mid>=v)build(l,mid,ch[pre][0],ch[now][0],v);    else build(mid+1,r,ch[pre][1],ch[now][1],v);}void get(int x,int y){    top1=top2=0;    while(top[x]!=top[y])    {        if(deep[top[x]]<deep[top[y]])swap(x,y);        st1[++top1]=root[pos[x]];        st2[++top2]=root[pos[top[x]]-1];        x=fa[top[x]];    }    if(deep[x]<deep[y])swap(x,y);    st1[++top1]=root[pos[x]];    st2[++top2]=root[pos[y]-1];}void trs(int x){    for(int i=1;i<=top1;i++)        st1[i]=ch[st1[i]][x];    for(int i=1;i<=top2;i++)        st2[i]=ch[st2[i]][x];}int solve(int l,int r,int k){    if(l==r)return b[l];    ll t=0;    for(int i=1;i<=top1;i++)        t+=sum[ch[st1[i]][0]];    for(int i=1;i<=top2;i++)        t-=sum[ch[st2[i]][0]];    int mid=(l+r)>>1;    if(t<k)        {trs(1);return solve(mid+1,r,k-t);}    else        {trs(0);return solve(l,mid,k);}}int main(){    //freopen("tt.in","r",stdin);    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]),b[i]=a[i];    sort(b+1,b+1+n);    for(int i=1;i<=n;i++)        a[i]=lower_bound(b+1,b+1+n,a[i])-b;    for(int i=1,x,y;i<n;i++)    {        scanf("%d%d",&x,&y);        add(x,y);add(y,x);    }    dfs(1,0);    dfs1(1,0,1);    for(int i=1;i<=n;i++)        build(1,n,root[i-1],root[i],val[i]);    for(int x,y,k;m--;)    {        scanf("%d%d%d",&x,&y,&k);x^=ans;        get(x,y);        printf("%d",ans=solve(1,n,k));        if(m)puts("");    }       return 0;}
0 0