zoukankan      html  css  js  c++  java
  • BZOJ2588 Spoj 10628. Count on a tree

    首先,这是一道坑题,我拍了几百组数据都是对的,交上去就WA,原因下面会讲。。。

    一开始我觉得要链剖,后来ZYH说。。。只要dfs序就可以解题。

    然后,解法嘛。。。就是每个点到根的链都建成一棵线段树,然后发现会MLE,于是就可持久化了所有线段树。

    在查询的时候呢,先找出两个点a, b的LCA,不妨叫c,然后找c的父亲叫d,每次比较k和seg[a] + seg[b] - seg[c] - seg[d]的大小就可以了。

      1 /**************************************************************
      2     Problem: 2588
      3     User: rausen
      4     Language: C++
      5     Result: Accepted
      6     Time:4396 ms
      7     Memory:51788 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstdlib>
     12 #include <cstring>
     13 #include <algorithm>
     14  
     15 using namespace std;
     16  
     17 struct tree_node{
     18     int pos, dep, v, fa[20];
     19 } tr[150000];
     20  
     21 struct edges{
     22     int next, to;
     23 }e[250000];
     24  
     25 struct segment{
     26     int lson, rson, sum;
     27 } seg[2500000];
     28  
     29 int n, m, tot, TOT, cnt, sz, ans;
     30 int X, Y, Z, K;
     31 int first[150000], V[150000], N[150000], root[150000], num[150000];
     32  
     33 void add_edge(int x, int y){
     34     e[++TOT].next = first[x];
     35     first[x] = TOT;
     36     e[TOT].to = y;
     37 }
     38  
     39 void add_Edges(int x, int y){
     40     add_edge(x, y);
     41     add_edge(y, x);
     42 }
     43  
     44 int find(int x){
     45     int l = 1, r = tot;
     46     while (l < r){
     47         int mid = (l + r) >> 1;
     48         if (N[mid] < x) l = mid + 1;
     49         else r = mid;
     50     }
     51     return l;
     52 }
     53  
     54 void dfs(int p){
     55     num[++cnt] = p, tr[p].pos = cnt;
     56     int x, y;
     57     for (x = 1; x <= 16; ++x)
     58         if ((1 << x) < tr[p].dep) 
     59             tr[p].fa[x] = tr[tr[p].fa[x - 1]].fa[x - 1];
     60         else break;
     61     for (x = first[p]; x; x = e[x].next){
     62         y = e[x].to;
     63         if (tr[p].fa[0] != y){
     64             tr[y].fa[0] = p, tr[y].dep = tr[p].dep + 1;
     65             dfs(y);
     66         }
     67     }
     68 }
     69  
     70 void add(int l, int r, int x, int &y, int num){
     71     y = ++sz, seg[y].sum = seg[x].sum + 1;
     72     seg[y].lson = seg[x].lson, seg[y].rson = seg[x].rson;
     73     if (l == r) return;
     74     int mid = (l + r) >> 1;
     75     if (num <= mid)
     76         add(l, mid, seg[x].lson, seg[y].lson, num);
     77     else add(mid + 1, r, seg[x].rson, seg[y].rson, num);
     78 }
     79  
     80 int LCA(int x, int y){
     81     if (tr[x].dep < tr[y].dep) swap(x, y);
     82     int tmp = tr[x].dep - tr[y].dep;
     83     for (int i = 0; i <= 16; ++i)
     84         if (tmp & (1 << i)) x = tr[x].fa[i];
     85     for (int i = 16; i >= 0; --i)
     86         if (tr[x].fa[i] != tr[y].fa[i])
     87             x = tr[x].fa[i], y = tr[y].fa[i];
     88     if (x == y) return x;
     89     else return tr[x].fa[0];
     90 }
     91  
     92 int query(int x, int y, int K){
     93     int a = x, b = y, c = LCA(x, y), d = tr[c].fa[0];
     94     a = root[tr[a].pos], b = root[tr[b].pos], c = root[tr[c].pos], d = root[tr[d].pos];
     95     int l = 1, r = tot;
     96     while (l < r){
     97         int mid = (l + r) >> 1;
     98         int tmp = seg[seg[a].lson].sum + seg[seg[b].lson].sum - seg[seg[c].lson].sum - seg[seg[d].lson].sum;
     99         if (tmp >= K)
    100             r = mid, a = seg[a].lson, b = seg[b].lson, c = seg[c].lson, d = seg[d].lson;
    101         else
    102             K -= tmp, l = mid + 1, a = seg[a].rson, b = seg[b].rson, c = seg[c].rson, d = seg[d].rson;
    103     }
    104     return N[l];
    105 }
    106  
    107 int main(){
    108     scanf("%d%d", &n, &m);
    109     for (int i = 1; i <= n; ++i){
    110         scanf("%d", &tr[i].v);
    111         V[i] = tr[i].v;
    112     }
    113     sort(V + 1, V + n + 1);
    114     N[++tot] = V[1];
    115     for (int i = 2; i <= n; ++i)
    116         if (V[i] != V[i - 1])
    117             N[++tot] = V[i];
    118     for (int i = 1; i <= n; ++i)
    119         tr[i].v = find(tr[i].v);
    120     for (int i = 1; i < n; ++i){
    121         scanf("%d%d", &X, &Y);
    122         add_Edges(X, Y);
    123     }
    124     cnt = 0;
    125     tr[1].fa[0] = 0, tr[1].dep = 1;
    126     dfs(1);
    127      
    128     root[0] = 0, seg[0].sum = seg[0].lson = seg[0].rson = 0;
    129     for (int i = 1; i <= n; ++i){
    130         int t = num[i];
    131         add(1, tot, root[tr[tr[t].fa[0]].pos], root[i], tr[t].v);
    132     }
    133     while (m--){
    134         scanf("%d%d%d", &X, &Y, &K);
    135         X ^= ans;
    136         ans = query(X ,Y ,K);
    137         printf("%d", ans);
    138         if (m) printf("
    ");
    139     }
    140     return 0;
    141 }
    View Code

     (WA的原因:太坑爹了,我把根的深度设成0,然后倍增乱搞的时候RE了。。。)

    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    程序员修神之路--容器技术为什么会这么流行
    程序员修神之路--kubernetes是微服务发展的必然产物
    程序员修神之路--有状态的服务其实可以做更多的事情
    程序员修神之路--要想做好微服务架构,并非易事!
    程序员修神之路--为什么有了SOA,我们还用微服务?
    程序员过关斩将--数据库的乐观锁和悲观锁并非真实的锁
    程序员修神之路--设计一套RPC框架并非易事
    计算机的诞生和简史
    记一次Linux修改MySQL配置不生效的问题
    为什么大多数公司都不重视技术?
  • 原文地址:https://www.cnblogs.com/rausen/p/4006116.html
Copyright © 2011-2022 走看看