zoukankan      html  css  js  c++  java
  • 《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
    ",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
  • 相关阅读:
    Android -- 桌面悬浮,仿360
    android 定时短信app之时间选择器(一)
    如何在Android中为TextView动态设置drawableLeft等
    装饰器3(装饰函数带参数)
    装饰器2(被装饰函数自带参数)
    装饰器1(被装饰函数不带参数)
    工资管理系统(初级实现)
    购物车程序
    python中read、readline、readlines之间的区别
    深复制与浅复制的区别
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13619213.html
Copyright © 2011-2022 走看看