《P2633 Count on a tree》

树上查询某一路径上的第k大。

首先,我们只需要处理出路径上的权值线段树即可。

我们建立根到u的前缀和主席树。

那么对于查询u,v。和树上距离的类似。

sum[u] + sum[v] - sum[lca(u,v]] - sum[fa[lca(u,v]]]。

因为这里的话,lca的值也需要算入。所以第二次减去lca的fa的值。这样就不会少去lca点的值了。

那么就可以查询了。

这里因为一个小错误一直RE,调了很久。。。。。

应该先让u ^= ans,再去求lca。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 1e5+5;
const int M = 2e5+5;
const LL Mod = 199999;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;
void FRE(){/*freopen("data1.in","r",stdin);
freopen("data1.out","w",stdout);*/}

int n,m,a[N],b[N],mp[N],rt[N],dep[N],f[N][20],lg[N],top = 0,len;
struct Node{int L,r;LL sum;}node[N*50];
vector<int> G[N];
void init()
{
    for(rg int i = 1;i < N;++i) lg[i] = lg[i-1]+((1<<lg[i-1]) == i);
}
int build(int L,int r)
{
    int idx = ++top;
    node[idx].sum = 0;
    if(L == r) return idx;
    int mid = (L+r)>>1;
    node[idx].L = build(L,mid);
    node[idx].r = build(mid+1,r);
    return idx;
}
void Pushup(int idx)
{
    node[idx].sum = node[node[idx].L].sum + node[node[idx].r].sum;
}
int update(int x,int L,int r,int pos)
{
    int idx = ++top;
    node[idx] = node[x];
    if(L == r){node[idx].sum++;return idx;}
    int mid = (L+r)>>1;
    if(mid >= pos) node[idx].L = update(node[x].L,L,mid,pos);
    else node[idx].r = update(node[x].r,mid+1,r,pos);
    Pushup(idx);
    return idx;
}
void dfs(int u,int fa)
{
    rt[u] = update(rt[fa],1,len,b[u]);
    dep[u] = dep[fa]+1,f[u][0] = fa;
    for(rg int i = 1;i <= lg[dep[u]];++i) f[u][i] = f[f[u][i-1]][i-1];
    for(auto v : G[u]) if(v != fa) dfs(v,u);
}
int LCA(int x,int y)
{
    if(dep[x] < dep[y]) swap(x,y);
    while(dep[x] > dep[y]) x = f[x][lg[dep[x]-dep[y]]-1];
    if(x == y) return x;
    for(rg int i = lg[dep[x]]-1;i >= 0;--i)
    {
        if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i];
    }
    return f[x][0];
}
int query_kth(int ll,int rr,int fa,int ffa,int L,int r,int k)
{
    if(L == r) return mp[L];
    int mid = (L+r)>>1;
    int lsum = node[node[ll].L].sum+node[node[rr].L].sum-node[node[fa].L].sum-node[node[ffa].L].sum;
    if(lsum >= k) return query_kth(node[ll].L,node[rr].L,node[fa].L,node[ffa].L,L,mid,k);
    else return query_kth(node[ll].r,node[rr].r,node[fa].r,node[ffa].r,mid+1,r,k-lsum);
}
int main()
{
    init();
    n = read(),m = read();
    for(rg int i = 1;i <= n;++i) a[i] = read(),b[i] = a[i];
    sort(a+1,a+n+1);
    len = unique(a+1,a+n+1)-a-1;
    for(rg int i = 1;i <= n;++i)
    {
        int pos = lower_bound(a+1,a+len+1,b[i])-a;
        mp[pos] = b[i],b[i] = pos;
    }
    for(rg int i = 1;i < n;++i)
    {
        int x,y;x = read(),y = read();
        G[x].push_back(y);
        G[y].push_back(x);
    }
    rt[0] = build(1,len);
    dfs(1,0);
    int ans = 0;
    while(m--)
    {
        int u,v,k;u = read(),v = read(),k = read();
        u ^= ans;
        int lca = LCA(u,v);
        ans = query_kth(rt[u],rt[v],rt[lca],rt[f[lca][0]],1,len,k);
        printf("%d\n",ans);
    }   
    system("pause");
}

/*
8 20
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8

*/
View Code

 

posted @ 2020-09-05 18:49  levill  阅读(170)  评论(0编辑  收藏  举报