zoukankan      html  css  js  c++  java
  • Count on a Tree

    传送门

    这次主席树要维护的是树上信息啦。

    其实主席树基本的思想还是用前缀和,那么我们就仿照一下,在树上做前缀和就好啦。我们令第(i)个节点所在的主席树维护该点到根节点路径上的所有数(值域是数的值),之后在计算的时候,以(v[p] + v[q] - v[lca(p,q)] - v[fa[lca(p,q)]])为标准来判定往哪边二分就可以了。

    直接在(dfs)的时候建树即可,我使用(ST)表求(lca),其他的也无所谓。这题还是很好写的。

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<vector>
    #include<map>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define fr friend inline
    #define y1 poj
    #define mp make_pair
    #define pr pair<int,int>
    #define fi first
    #define sc second
    #define pb push_back
    
    using namespace std;
    typedef long long ll;
    const int M = 200005;
    const int N = 1000005;
    
    const int INF = 1000000009;
    const double eps = 1e-7;
    
    int read()
    {
        int ans = 0,op = 1;char ch = getchar();
        while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
        while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
        return ans * op;
    }
    
    struct node
    {
       int ls,rs,v;
    }t[N<<3];
    
    struct edge
    {
       int next,to;
    }e[M<<1];
    
    int a[M],b[M],n,m,root[M<<1],la,x,y,z,head[M],ecnt,dep[M],dfn[M<<1],pos[M],idx,lg[M<<1];
    int st[22][M<<1],cnt,fat[M<<1],tot;
    
    void add(int x,int y)
    {
       e[++ecnt].to = y;
       e[ecnt].next = head[x];
       head[x] = ecnt;
    }
    
    void modify(int old,int &p,int l,int r,int pos)
    {
       p = ++cnt;
       t[p].ls = t[old].ls,t[p].rs = t[old].rs,t[p].v = t[old].v + 1;
       if(l == r) return;
       int mid = (l+r) >> 1;
       if(pos <= mid) modify(t[old].ls,t[p].ls,l,mid,pos);
       else modify(t[old].rs,t[p].rs,mid+1,r,pos);
    }
    
    int query(int p,int q,int f,int g,int l,int r,int k)
    {
       if(l == r) return l;
       int mid = (l+r) >> 1;
       int sum = t[t[p].ls].v + t[t[q].ls].v - t[t[f].ls].v - t[t[g].ls].v;
       if(k <= sum) return query(t[p].ls,t[q].ls,t[f].ls,t[g].ls,l,mid,k);
       else return query(t[p].rs,t[q].rs,t[f].rs,t[g].rs,mid+1,r,k - sum);
    }
    
    int Min(int p,int q)
    {
       return (dep[p] < dep[q]) ? p : q;
    }
    
    void dfs(int x,int fa)
    {
       dep[x] = dep[fa] + 1,dfn[++idx] = x,pos[x] = idx,fat[x] = fa;
       modify(root[fa],root[x],1,tot,a[x]);
       for(int i = head[x];i;i = e[i].next)
       {
          if(e[i].to != fa) dfs(e[i].to,x);
          dfn[++idx] = x;
       }
    }
    
    void build()
    {
       lg[0] = -1;
       rep(i,1,idx) st[0][i] = dfn[i];
       rep(i,1,idx) lg[i] = lg[i>>1] + 1;
       rep(j,1,lg[idx])
       rep(i,1,idx)
       {
          if(i + (1 << j) - 1 > idx) break;
          st[j][i] = Min(st[j-1][i],st[j-1][i + (1 << (j-1))]);
       }
    }
    
    int lca(int x,int y)
    {
       int kl = pos[x],kr = pos[y];
       if(kl > kr) swap(kl,kr);
       int k = lg[kr - kl + 1];
       return Min(st[k][kl],st[k][kr - (1 << k) + 1]);
    }
    
    int main()
    {
       n = read(),m = read();
       rep(i,1,n) a[i] = b[i] = read();
       sort(b+1,b+1+n);
       tot = unique(b+1,b+1+n) - b - 1;
       rep(i,1,n) a[i] = lower_bound(b+1,b+1+tot,a[i]) - b;
       rep(i,1,n-1) x = read(),y = read(),add(x,y),add(y,x);
       dfs(1,0),build();
       rep(i,1,m)
       {
          x = read(),y = read(),z = read();
          x ^= la;
          int g = lca(x,y),f = fat[g];
          //printf("#%d %d %d %d
    ",x,y,g,f);
          int now = query(root[x],root[y],root[f],root[g],1,tot,z);
          //printf("$%d
    ",now);
          la = b[now];
          printf("%d
    ",la);
       }
       return 0;
    }
    
    
  • 相关阅读:
    Java实现“睡排序”——线程池Executors的使用
    浅谈HashMap与线程安全 (JDK1.8)
    Ubuntu 16 Java Develop环境快速搭建
    Spring Boot在反序列化过程中:jackson.databind.exc.InvalidDefinitionException cannot deserialize from Object value
    Java 8 – Map排序
    vue指令优化网络图片加载速度
    如何实现小于12px的字体效果
    两种以上方式实现已知或者未知宽度的垂直水平居中
    C# winform窗体间传值(使用委托或事件)
    C#栈Stack的使用
  • 原文地址:https://www.cnblogs.com/captain1/p/10102715.html
Copyright © 2011-2022 走看看