P2633 Count on a tree 树链上第k大

题意:在线询问树一条练上的第K大

解:主席树查询 sum[x]+sum[y]-sum[lca(x,y)]-sum[f[lca]];

这里的主席树建树实在dfs过程当中build的

#include<bits/stdc++.h>
#define en '\n'
#define ll long long
const int maxn =1e5+10;
using namespace std;
int rd(){int t;scanf("%d",&t);return t;}
vector<int>vec[maxn];
const int logm=19;
const int maxm=maxn*67;
int n,m,f[maxn][logm],a[maxn],tot,dep[maxn],rt[maxn];
int ls[maxm],rs[maxm],sm[maxm];
void update(int &x,int y,int l,int r,int val){
        x=++tot;sm[x]=sm[y]+1;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(val<=mid)update(ls[x],ls[y],l,mid,val),rs[x]=rs[y];
        else update(rs[x],rs[y],mid+1,r,val),ls[x]=ls[y];
}
vector<int>b;
void dfs(int x,int fa){
    dep[x]=dep[fa]+1;
    update(rt[x],rt[fa],0,b.size()-1,a[x]);
    f[x][0]=fa;
    for(int i=1;i<logm;i++){
        f[x][i]=f[f[x][i-1]][i-1];
    }
    for(int i=0;i<vec[x].size();i++){
        int y=vec[x][i];if(y==fa)continue;
        dfs(y,x);
    }
}
int lca(int x,int y){
    if(dep[y]<dep[x])swap(x,y);
    int t=dep[y]-dep[x];
    for(int i=logm-1;i>=0;--i){
        if((t>>i)&1){
            y=f[y][i];
        }
    }
    if(y==x)return x;
    for(int i=logm-1;i>=0;--i){
        if(f[x][i]==f[y][i])continue;
        x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
int ask(int pos1,int pos2,int neg1,int neg2,int l,int r,int k){
    if(l==r)return l;
    int tem=sm[ls[pos1]]+sm[ls[pos2]]-sm[ls[neg1]]-sm[ls[neg2]];
    int mid=(l+r)>>1;
    if(k<=tem)return ask(ls[pos1],ls[pos2],ls[neg1],ls[neg2],l,mid,k);
    else return ask(rs[pos1],rs[pos2],rs[neg1],rs[neg2],mid+1,r,k-tem);
}
signed main()
{
    #ifdef local
    freopen("input2.txt","r",stdin);
    #endif
    #define mem(a,b) memset(a,b,sizeof(a))
    #define pb push_back
    cin>>n>>m;
    for(int i=1;i<=n;i++){
     a[i]=rd();
     b.pb(a[i]);
    }
    sort(b.begin(),b.end());
    b.resize(unique(b.begin(),b.end())-b.begin());
    for(int i=1;i<=n;i++){
        a[i]=lower_bound(b.begin(),b.end(),a[i])-b.begin();
    }
    for(int i=1;i<n;i++){
        int x=rd(),y=rd();
        vec[x].pb(y),vec[y].pb(x);
    }
    dfs(1,0);
    int las=0;
    while(m--){
        int x=rd(),y=rd(),k=rd();
        x^=las;int LCA=lca(x,y);
        las=b[ask(rt[x],rt[y],rt[LCA],rt[f[LCA][0]],0,b.size()-1,k)];
        cout<<las<<en;
    }
    return  0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值