2588: Spoj 10628. Count on a tree (主席树,树上路径第K大值)

来源:互联网 发布:盖伊福克斯面具淘宝 编辑:程序博客网 时间:2024/05/22 06:19

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 7448  Solved: 1815
[Submit][Status][Discuss]

Description

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

M行,表示每个询问的答案。最后一个询问不输出换行符

Sample Input

8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
0 5 2
10 5 3
11 5 4
110 8 2

Sample Output

2
8
9
105
7

分析:求树上的第K大值,主席树题,但是怎么建立主席树,这里可以不用轻重链剖分,我们只需要记录每个节点到根节点的路径信息(用权值线段树)统计,结果就是root【L】+root【R】-root【lca(L,R)】-root【fa【lca(L,R) 】】;

有一个需要注意的点就是题上给的边是无向边。还有就是求LCA需要用ST算法优化。

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <stack>#include <map>#include <set>#include <vector>#include <queue>#define mem(p,k) memset(p,k,sizeof(p));#define pb push_back#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define inf 0x3f3f3f3f//#define ll long longusing namespace std;const int N=100010 ;int n,m,len,tot;int root[N],dep[N];long long  a[N];int ls[N*30],rs[N*30],s[N*30];bool bk[N];int tot2,dp[N<<1][20],R[N<<1],first[N],ver[N<<1],fa[N];vector<long long> vec;vector<int> edg[N];int edg2[N];int Hash(long long k){    return lower_bound(vec.begin(),vec.end(),k)-vec.begin()+1;}void update(int k,int val,int pre,int &now,int l,int r){    now=++tot;    ls[now]=ls[pre];    rs[now]=rs[pre];    s[now]=s[pre]+val;    if(l==r)return;    int m=(l+r)>>1;    if(k<=m)update(k,val,ls[pre],ls[now],l,m);    else update(k,val,rs[pre],rs[now],m+1,r);}void build(int d,int pre,int now){    update(Hash(a[now]),1,root[pre],root[now],1,len);    dep[now]=d;    bk[now]=1;    ver[++tot2]=now,first[now]=tot2;R[tot2]=d;fa[now]=pre;    int l=edg[now].size();    if(!l)return;    for(int i=0;i<l;i++){        if(bk[edg[now][i]])continue;        build(d+1,now,edg[now][i]);        ver[++tot2]=now,R[tot2]=d;    }}void ST(int n){    for(int i=1;i<=n;i++)        dp[i][0] = i;    for(int j=1;(1<<j)<=n;j++)    {        for(int i=1;i+(1<<j)-1<=n;i++)        {            int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];            dp[i][j] = R[a]<R[b]?a:b;        }    }}int RMQ(int l,int r){    int k=log(r-l+1)/log(2);    int a = dp[l][k], b = dp[r-(1<<k)+1][k];    return R[a]<R[b]?a:b;}int finlca(int l,int r){    int x = first[l] , y = first[r];    if(x > y) swap(x,y);    int res = RMQ(x,y);    return ver[res];}long long Query(int l,int r,int k,int f){    int ll=1,rr=len,cur=Hash(a[f]);    l=root[l],r=root[r],f=root[f];    while(ll<=rr){        if(ll==rr){            return vec[ll-1];        }        int m=(ll+rr)>>1;        int sum=s[ls[l]]+s[ls[r]]-2*s[ls[f]]+(cur<=m && cur>=ll?1:0);                if(k<=sum){            rr=m;            l=ls[l];            r=ls[r];            f=ls[f];        }        else{            ll=m+1;            k-=sum;            l=rs[l];            r=rs[r];            f=rs[f];        }    }}int main(){    int l,r,k;    scanf("%d%d",&n,&m);    vec.clear();    mem(ls,0);    mem(rs,0);    mem(s,0);    mem(root,0);    tot2=0;    for(int i=1;i<=n;i++){        scanf("%lld",a+i);        vec.pb(a[i]);    }    sort(vec.begin(),vec.end());    vec.erase(unique(vec.begin(),vec.end()),vec.end());    len=vec.size();    for(int i=0;i<=n;i++)edg[i].clear();    mem(edg2,0);    mem(bk,0);    for(int i=1;i<n;i++){        scanf("%d%d",&l,&r);        edg[l].pb(r);        edg[r].pb(l);    }    tot=0;    build(1,0,1);    ST(tot2);    long long last=0;    while(m--){        scanf("%d%d%d",&l,&r,&k);        l^=last;        printf("%lld",last=Query(l,r,k,finlca(l,r)));        if(m)printf("\n");    }    return 0;}


阅读全文
0 0
原创粉丝点击