zoukankan      html  css  js  c++  java
  • SPOJ QTREE 系列解题报告

    题目一 : SPOJ 375 Query On a Tree

    http://www.spoj.com/problems/QTREE/

    给一个树,求a,b路径上最大边权,或者修改a,b边权为t。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 const int maxn = 200000 + 5;
      9 
     10 int N,pos=0;
     11 char ss[50];
     12 
     13 struct SegmentTree{
     14     int l,r,flag;
     15     int maxv,minv;
     16 }Node[maxn * 10];
     17 
     18 int e[maxn][4];
     19 int size[maxn],dep[maxn],top[maxn],son[maxn];
     20 int fa[maxn],Segnum[maxn],Treenum[maxn];
     21 
     22 int tot = 0;
     23 int first[maxn],next[maxn*2];
     24 int u[maxn*2],v[maxn*2];
     25 
     26 void clear();
     27 void change(int&,int&);
     28 void Add(int,int);
     29 void dfs_1(int,int,int);
     30 void dfs_2(int,int);
     31 void build(int,int,int);
     32 void update(int,int,int,int);
     33 int query(int,int,int);
     34 int find_max(int,int);
     35 void rever(int,int,int);
     36 void get_rever(int,int);
     37 void pushdown(int);
     38 void pushup(int);
     39 
     40 int main(){
     41     int tcase;
     42     scanf("%d",&tcase);
     43     while(tcase --){
     44         clear();
     45         int x,y,z;
     46         scanf("%d",&N);
     47         for(int i = 1;i < N;++ i){
     48             scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
     49             Add(e[i][0],e[i][1]);
     50             Add(e[i][1],e[i][0]);
     51         }    
     52         
     53         dfs_1(1,0,1);
     54         dfs_2(1,1);
     55         build(1,1,N);    
     56         for(int i = 1;i < N;++ i){
     57             if(dep[e[i][0]] > dep[e[i][1]])
     58                 swap(e[i][0],e[i][1]);
     59             update(1,Segnum[e[i][1]],Segnum[e[i][1]],e[i][2]);    
     60         }
     61         while(1){
     62             scanf("%s",ss);
     63             if(ss[0] == 'D')
     64                 break;
     65             scanf("%d%d",&x,&y);
     66             if(ss[0] == 'C'){
     67                 update(1,Segnum[e[x][1]],Segnum[e[x][1]],y);
     68             }
     69             else if(ss[0] == 'Q'){
     70                 printf("%d
    ",find_max(x,y));
     71             }
     72             else if(ss[0] == 'N'){
     73                 get_rever(x,y);
     74             }
     75         }
     76     } 
     77     return 0;
     78 }
     79 
     80 void clear(){
     81     pos = 0;tot = 0;
     82     memset(son,0,sizeof son);
     83     memset(first,0,sizeof first);
     84 }
     85 void Add(int s,int t){
     86     ++ tot;
     87     u[tot] = s;v[tot] = t;
     88     next[tot] = first[u[tot]];
     89     first[u[tot]] = tot;
     90 }
     91 void dfs_1(int now,int f,int depth){
     92     size[now] = 1;
     93     fa[now] = f;
     94     dep[now] = depth;
     95     
     96     for(int i = first[now];i;i = next[i]){
     97         if(v[i] != f){
     98             dfs_1(v[i],now,depth + 1);
     99             size[now] += size[v[i]];
    100             if(!son[now] || size[v[i]] > size[son[now]])
    101                 son[now] = v[i];
    102         }
    103     }
    104     return;
    105 }
    106 
    107 void dfs_2(int now,int ances){
    108     top[now] = ances;
    109     Segnum[now] = ++ pos;
    110     Treenum[Segnum[now]] = now;
    111     
    112     if(!son[now])return;
    113     dfs_2(son[now],ances);
    114     
    115     for(int i = first[now];i;i = next[i]){
    116         if(v[i] != son[now] && v[i] != fa[now]){
    117             dfs_2(v[i],v[i]);
    118         }
    119     }
    120     return;
    121 }
    122 
    123 void build(int o,int l,int r){
    124     Node[o].l = l;
    125     Node[o].r = r;
    126     Node[o].minv = Node[o].maxv = 0;
    127     Node[o].flag = 0;
    128     if(l == r)
    129         return;
    130     int Mid = (l + r) >> 1;
    131     build(o<<1,l,Mid);
    132     build(o<<1|1,Mid+1,r);
    133 }
    134 
    135 void update(int o,int l,int r,int v){
    136     if(Node[o].l == l && Node[o].r == r){
    137         Node[o].minv = Node[o].maxv = v;
    138         Node[o].flag = 0;
    139         return;
    140     }
    141     int Mid = (Node[o].l + Node[o].r) >> 1;
    142     pushdown(o);
    143     if(r <= Mid)
    144         update(o<<1,l,r,v);
    145     else if(l > Mid)
    146         update(o<<1|1,l,r,v);
    147     pushup(o);
    148 }
    149 void pushdown(int o){
    150     if(Node[o].l == Node[o].r)
    151         return;
    152     int lc = o << 1,rc = o << 1 | 1;
    153     if(Node[o].flag){
    154         Node[o].flag = 0;
    155         Node[lc].flag ^= 1;
    156         Node[rc].flag ^= 1;
    157         change(Node[rc].minv,Node[rc].maxv);
    158         change(Node[lc].maxv,Node[lc].minv);
    159     }
    160 }
    161 void pushup(int o){
    162     int lc = o << 1,rc = o << 1 | 1;
    163     Node[o].maxv = max(Node[lc].maxv,Node[rc].maxv);
    164     Node[o].minv = min(Node[lc].minv,Node[rc].minv);
    165 }
    166 
    167 int query(int o,int l,int r){
    168     if(Node[o].l == l && Node[o].r == r){
    169         return Node[o].maxv;
    170     }
    171     int Mid = (Node[o].l + Node[o].r) >> 1;
    172     pushdown(o);
    173     if(r <= Mid)
    174         return query(o<<1,l,r);
    175     else if(l > Mid)
    176         return query(o<<1|1,l,r);
    177     else
    178         return max(query(o<<1,l,Mid),query(o<<1|1,Mid+1,r));
    179     pushup(o);
    180 }
    181 void rever(int o,int l,int r){
    182     if(Node[o].l == l && Node[o].r == r){
    183         change(Node[o].maxv,Node[o].minv);
    184         Node[o].flag ^= 1;
    185         return;
    186     }
    187     int Mid = (Node[o].l + Node[o].r) >> 1;
    188     pushdown(o);
    189     if(r <= Mid)
    190         rever(o<<1,l,r);
    191     else if(l > Mid)
    192         rever(o<<1|1,l,r);
    193     else{
    194         rever(o<<1,l,Mid);
    195         rever(o<<1|1,Mid+1,r);
    196     }
    197     pushup(o);
    198 }
    199 int find_max(int x,int y){
    200     int f1 = top[x],f2 = top[y];
    201     int ret = -100000;
    202     
    203     while(f1 != f2){
    204         if(dep[f1] < dep[f2]){
    205             swap(f1,f2);
    206             swap(x,y);
    207         }
    208         ret = max(ret,query(1,Segnum[f1],Segnum[x]));
    209         x = fa[f1];f1 = top[x];
    210     }
    211     
    212     if(x == y)return ret;
    213     if(dep[x] < dep[y]){
    214         ret = max(ret,query(1,Segnum[son[x]],Segnum[y]));
    215     }
    216     else{
    217         ret = max(ret,query(1,Segnum[son[y]],Segnum[x]));
    218     }
    219     
    220     return ret;
    221 }
    222 
    223 void get_rever(int x,int y){
    224     int f1 = top[x],f2 = top[y];
    225     
    226     while(f1 != f2){
    227         if(dep[f1] < dep[f2]){
    228             swap(f1,f2);
    229             swap(x,y);
    230         }
    231         rever(1,Segnum[f1],Segnum[x]);
    232         x = fa[f1];f1 = top[x];
    233     }
    234     if(x == y)return;//如果是针对边的操作, 这个东西不能少。。 
    235     if(dep[x] < dep[y]){
    236         rever(1,Segnum[son[x]],Segnum[y]);//如果是边权,注意这里的写法。要下放。 
    237     }
    238     else{
    239         rever(1,Segnum[son[y]],Segnum[x]);
    240     }
    241     return;
    242 }
    243 
    244 void change(int &a,int &b){
    245     int tp1 = a,tp2 = b;
    246     a = -tp2;b = -tp1;
    247     return;
    248 }
    树链剖分

     TLE的但是保证 不WA的LCT

      1 #include <cstdlib>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 const int N = 20000 + 5;
      9 
     10 int n;
     11 int top, st[N << 1];
     12 int fa[N], c[N][2], val[N], mx[N];
     13 bool rev[N];
     14 
     15 void pushup(int x) {
     16   int l = c[x][0], r = c[x][1];
     17   mx[x] = x;
     18   if(l && val[mx[l]] > val[mx[x]]) mx[x] = mx[l];
     19   if(r && val[mx[r]] > val[mx[x]]) mx[x] = mx[r];
     20 }
     21 
     22 void pushdown(int x) {
     23   int l = c[x][0], r = c[x][1];
     24   if(rev[x]) {
     25     rev[x] ^= 1; rev[l] ^= 1; rev[r] ^= 1;
     26     swap(c[x][0], c[x][1]);
     27   }
     28 }
     29 
     30 bool isroot(int x) {
     31   return c[fa[x]][0] != x && c[fa[x]][1] != x;
     32 }
     33 
     34 void rotate(int x) {
     35   int y = fa[x], z = fa[y], l, r;
     36   if(c[y][0] == x) l = 0, r = 1;
     37   else l = 1, r = 0;
     38   if(!isroot(y)) {
     39     if(c[z][0] == y) c[z][0] = x;
     40     else c[z][1] = x;
     41   }
     42   fa[x] = z; fa[y] = x; fa[c[x][r]] = y;
     43   c[y][l] = c[x][r]; c[x][r] = y;
     44   pushup(y); pushup(x);
     45 }
     46 
     47 void splay(int x) {
     48   top = 0; st[++ top] = x;
     49   for(int i = x; !isroot(i); i = fa[i])
     50     st[++ top] = fa[i];
     51   while(top) pushdown(st[top --]);
     52   while(!isroot(x)) {
     53     int y = fa[x], z = fa[y];
     54     if(!isroot(y)) {
     55       if((c[z][0] == y) ^ (c[y][0] == x)) rotate(x);
     56       else rotate(y);
     57     }
     58     rotate(x);
     59   }
     60   pushup(x);
     61 }
     62 
     63 void access(int x) {
     64   int t = 0;
     65   while(x) {
     66     splay(x); c[x][1] = t;
     67     t = x;
     68     pushup(x); x = fa[x];
     69   }
     70 }
     71 
     72 void mroot(int x) {
     73   access(x); splay(x); rev[x] ^= 1;
     74 }
     75 
     76 void link(int a, int b) {
     77   mroot(a); fa[a] = b;
     78 }
     79 
     80 void cut(int a, int b) {
     81   mroot(a); access(b); splay(b);
     82   c[b][0] = fa[c[b][0]] = 0;
     83 }
     84 
     85 int Q(int a, int b) {
     86   mroot(a); access(b); splay(b);
     87   return val[mx[b]];
     88 }
     89 
     90 void C(int a, int b) {
     91   access(a + n); splay(a + n);
     92   val[a + n] = b;
     93 }
     94 
     95 int main() {
     96   char ss[10];
     97   int a, b, t, cs;
     98   scanf("%d", &t);
     99   while(t --) {
    100     memset(fa, 0, sizeof fa);
    101     memset(rev, 0, sizeof rev);
    102     memset(c, 0, sizeof c);
    103     memset(mx, 0, sizeof mx);
    104     memset(val, 0, sizeof val);
    105     scanf("%d", &n);
    106     for(int i = 1; i < n; ++ i) {
    107       scanf("%d%d%d", &a, &b, &cs);
    108       val[i + n] = cs;
    109       mx[i + n] = i + n;
    110       link(a, i + n); link(b, i + n);
    111     }
    112     while(1) {
    113       scanf("%s", ss);
    114       if(ss[0] == 'D') break;
    115       if(ss[0] == 'C') {
    116         scanf("%d%d", &a, &b);
    117         C(a, b);
    118       }
    119       else {
    120         scanf("%d%d", &a, &b);
    121         printf("%d
    ", Q(a, b));
    122       }
    123     }
    124   }
    125   return 0;
    126 }
    lct

    题目二: SPOJ Query On a Tree II

    题目大意:

    给一个树,两个操作,求a->b距离,求a->b路径上的第k个点。

    算法讨论:

    用LCA来维护,第k个点也用Lca来跳就可以啦。

      1 #include <cstdlib>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 
      9 const int N = 20000 + 5;
     10 
     11 int n, cnt;
     12 int head[N], fa[N], f[N][16];
     13 int dis[N], depth[N];
     14 
     15 struct Edge {
     16   int from, to, dis, next;
     17 }edges[N << 1];
     18 
     19 void insert(int from, int to, int w) {
     20   ++ cnt;
     21   edges[cnt].from = from; edges[cnt].to = to; edges[cnt].dis = w;
     22   edges[cnt].next = head[from]; head[from] = cnt;
     23 }
     24 
     25 void build(int u, int f) {
     26   fa[u] = f;
     27   for(int i = head[u]; i; i = edges[i].next) {
     28     int v = edges[i].to;
     29     if(v != f) {
     30       dis[v] = dis[u] + edges[i].dis;
     31       depth[v] = depth[u] + 1;
     32       build(v, u);
     33     }
     34   }
     35 }
     36 
     37 void prepare() {
     38   memset(f, -1, sizeof f);
     39   for(int i = 1; i <= n; ++ i) f[i][0] = fa[i];
     40   for(int j = 1; (1 << j) <= n; ++ j) {
     41     for(int i = 1; i <= n; ++ i) {
     42       if(f[i][j - 1] != -1) {
     43         f[i][j] = f[f[i][j - 1]][j - 1];
     44       }
     45     }
     46   }
     47 }
     48 
     49 int lca(int a, int b) {
     50   int i;
     51   if(depth[a] < depth[b]) swap(a, b);
     52   for(i = 0; (1 << i) <= depth[a]; ++ i);
     53   -- i;
     54   for(int j = i; j >= 0; -- j) {
     55     if(depth[a] - depth[b] >= (1 << j))
     56       a = f[a][j];
     57   }
     58   if(a == b) return a;
     59   for(int j = i; j >= 0; -- j) {
     60     if(f[a][j] != -1 && f[a][j] != f[b][j]) {
     61       a = f[a][j]; b = f[b][j];
     62     }
     63   }
     64   return f[a][0];
     65 }
     66 
     67 int splca(int a, int len) {
     68   int i;
     69   for(i = 0; (1 << i) <= depth[a]; ++ i);
     70   -- i;
     71   for(int j = i; j >= 0; -- j) {
     72     if(depth[a] - len >= (1 << j)) {
     73       a = f[a][j];
     74     }
     75   }
     76   return a;  
     77 }
     78 
     79 int Q(int a, int b) {
     80   return dis[a] + dis[b] - 2 * dis[lca(a, b)];
     81 }
     82 
     83 int K(int a, int b, int c) {
     84   int Lca = lca(a, b), res;
     85   if(depth[a] - depth[Lca] + 1 >= c) {
     86     res = splca(a, depth[Lca] + (depth[a] - depth[Lca]) - c + 1);
     87   }
     88   else {
     89     c -= (depth[a] - depth[Lca]);
     90     res = splca(b, depth[Lca] + c - 1);
     91   }
     92   return res;
     93 }
     94 
     95 void clear() {
     96   cnt = 0;
     97   memset(head, 0, sizeof head);
     98 }
     99 
    100 int main() {
    101   int t, u, v, w, a, b, c;
    102   char ss[10];
    103   bool flag = false;
    104   scanf("%d", &t);
    105   while(t --) {
    106     if(flag) puts("");
    107     flag = true;
    108     clear();
    109     scanf("%d", &n);
    110     for(int i = 1; i < n; ++ i) {
    111       scanf("%d%d%d", &u, &v, &w);
    112       insert(u, v, w); insert(v, u, w);
    113     }
    114     depth[1] = 1;
    115     dis[1] = 0;
    116     build(1, 0);
    117     prepare();
    118     while(1) {
    119       scanf("%s", ss);
    120       if(ss[0] == 'D') {
    121         if(ss[1] == 'O') break;
    122         else {
    123           scanf("%d%d", &a, &b);
    124           printf("%d
    ", Q(a, b));
    125         }
    126       }
    127       else {
    128         scanf("%d%d%d", &a, &b, &c);
    129         printf("%d
    ", K(a, b, c));
    130       }
    131     }
    132   }
    133   return 0;
    134 }
    Q2 LCA版

    题目三 SPOJ Query On a Tree III

    题目大意:

    给出一棵树,每个点有权值,而且互不相同。求以某个点为根的子树中第k小的权值是哪个点。

    算法讨论:

    我的第一个做法是可持久化线段树 + 区间第K小值。我们知道一个点的子树在DFS序中一定是连续的,所以我们可以查询这个区间的第K小值。这就是可持久化线段树的应用。注意可持久化线段树是NlogN的空间,我居然忘记了,只开了原来的4倍。。。所以有三个点re了。

      1 #include <cstdlib>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 
      9 const int N = 150000 + 5;
     10 
     11 int n, m, cnt, tot, pos;
     12 int fa[N], size[N], num[N], mx[N], w[N];
     13 int root[N], rank[N], son[N], head[N], seg[N];
     14 
     15 struct Edge {
     16   int from, to, next;
     17 }edges[N << 1];
     18 
     19 struct SegTree {
     20   int l, r, size;
     21 }Node[N * 16];//注意可持久化线段树是NlogN的空间
     22 
     23 struct data {
     24   int v, pos, id;
     25   bool operator < (const data &k) const {
     26     return v < k.v;
     27   }
     28 }a[N];
     29 
     30 void insert(int from, int to) {
     31   ++ cnt;
     32   edges[cnt].from = from; edges[cnt].to = to;
     33   edges[cnt].next = head[from]; head[from] = cnt;
     34 }
     35 
     36 void dfs_1(int x, int f) {
     37   size[x] = 1;
     38   fa[x] = f;
     39   for(int i = head[x]; i; i = edges[i].next) {
     40     int v = edges[i].to;
     41     if(v != f) {
     42       dfs_1(v, x);
     43       size[x] += size[v];
     44       if(!son[x] || size[v] > size[son[x]])
     45         son[x] = v;
     46     }
     47   }
     48 }
     49 
     50 void dfs_2(int x, int ances) {
     51   mx[x] = num[x] = ++ pos;
     52   seg[pos] = x;
     53   if(!son[x]) return;
     54   dfs_2(son[x], ances);
     55   mx[x] = max(mx[x], mx[son[x]]);
     56   for(int i = head[x]; i; i = edges[i].next) {
     57     int v = edges[i].to;
     58     if(v != fa[x] && v != son[x]) {
     59       dfs_2(v, v);
     60       mx[x] = max(mx[x], mx[v]);
     61     }
     62   }
     63 }
     64 
     65 void build(int &o, int l, int r) {
     66   o = ++ tot;
     67   Node[o].l = Node[o].r = Node[o].size = 0;
     68   if(l >= r) return;
     69   int mid = (l + r) >> 1;
     70   build(Node[o].l, l, mid);
     71   build(Node[o].r, mid + 1, r);
     72 }
     73 
     74 void update(int pre, int &o, int l, int r, int kth) {
     75   o = ++ tot;
     76   Node[o] = Node[pre];
     77   Node[o].size ++;
     78   if(l >= r) return;
     79   int mid = (l + r) >> 1;
     80   if(kth <= mid)
     81     update(Node[pre].l, Node[o].l, l, mid, kth);
     82   else
     83     update(Node[pre].r, Node[o].r, mid + 1, r, kth);
     84 }
     85 
     86 int query(int r1, int r2, int l, int r, int kth) {
     87   if(l >= r) return l;
     88   int lc = Node[Node[r2].l].size - Node[Node[r1].l].size;
     89   int mid = (l + r) >> 1;
     90   if(lc >= kth) {
     91     int ans = query(Node[r1].l, Node[r2].l, l, mid, kth);
     92     return ans;
     93   }
     94   else {
     95     int ans = query(Node[r1].r, Node[r2].r, mid + 1, r, kth - lc);
     96     return ans;
     97   }
     98 }
     99 
    100 int Q(int x, int k) {
    101   int l = num[x], r = mx[x];
    102   return  a[query(root[l - 1], root[r], 1, n, k)].id;
    103 }
    104 
    105 int main() {
    106   int u, v, x, k;
    107   scanf("%d", &n);
    108   for(int i = 1; i <= n; ++ i) scanf("%d", &w[i]);
    109   for(int i = 1; i < n; ++ i) {
    110     scanf("%d%d", &u, &v);
    111     insert(u, v); insert(v, u);
    112   }
    113   dfs_1(1, 0); dfs_2(1, 1);
    114   for(int i = 1; i <= n; ++ i) {
    115     a[i].v = w[seg[i]];
    116     a[i].pos = i;
    117     a[i].id = seg[i];
    118   }
    119   sort(a + 1, a + n + 1);
    120   for(int i = 1; i <= n; ++ i) {
    121     rank[a[i].pos] = i;
    122   }
    123   build(root[0], 1, n);
    124   for(int i = 1; i <= n; ++ i) {
    125     update(root[i - 1], root[i], 1, n, rank[i]);
    126   }
    127   scanf("%d", &m);
    128   for(int i = 1; i <= m; ++ i) {
    129     scanf("%d%d", &x, &k);
    130     printf("%d
    ", Q(x, k));
    131   }
    132   return 0;
    133 }
    可持久化线段树+树剖
      1 #include <cstdlib>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 
      9 const int N = 100000 + 5;
     10 
     11 int n, m, cnt, tot, pos;
     12 int fa[N], num[N], mx[N], w[N], st[N << 1];
     13 int root[N], rank[N], head[N], seg[N], fast[N];
     14 
     15 struct Edge {
     16   int from, to, next;
     17 }edges[N << 1];
     18 
     19 struct SegTree {
     20   int l, r, size;
     21 }Node[N * 20];
     22 
     23 struct data {
     24   int v, pos, id;
     25   bool operator < (const data &k) const {
     26     return v < k.v;
     27   }
     28 }a[N];
     29 
     30 //seg[i]  the ith pos is seg[i]
     31 //num[i] the i's pos in the segment tree.
     32 void dfs() {
     33   int top = 0;
     34   st[++ top] = 1;
     35   while(top) {
     36     int now = st[top], f = fast[top];
     37     top --;
     38     if(!num[now]) {
     39       num[now] = ++ pos;
     40       mx[now] = num[now];
     41       st[++ top] = now;
     42       fa[now] = f;
     43       for(int i = head[now]; i; i = edges[i].next) {
     44         if(edges[i].to != f) {
     45           st[++ top] = edges[i].to;
     46           fast[top] = now;
     47         }
     48       }
     49     }
     50   }
     51   for(int i = 1; i <= n; ++ i)
     52     seg[num[i]] = i;
     53   for(int i = n; i >= 1; -- i) {
     54     mx[fa[seg[i]]] = max(mx[seg[i]], mx[fa[seg[i]]]);
     55   }
     56 }
     57 
     58 void insert(int from, int to) {
     59   ++ cnt;
     60   edges[cnt].from = from; edges[cnt].to = to;
     61   edges[cnt].next = head[from]; head[from] = cnt;
     62 }
     63 
     64 void build(int &o, int l, int r) {
     65   o = ++ tot;
     66   Node[o].l = Node[o].r = Node[o].size = 0;
     67   if(l >= r) return;
     68   int mid = (l + r) >> 1;
     69   build(Node[o].l, l, mid);
     70   build(Node[o].r, mid + 1, r);
     71 }
     72 
     73 void update(int pre, int &o, int l, int r, int kth) {
     74   o = ++ tot;
     75   Node[o] = Node[pre];
     76   Node[o].size ++;
     77   if(l >= r) return;
     78   int mid = (l + r) >> 1;
     79   if(kth <= mid)
     80     update(Node[pre].l, Node[o].l, l, mid, kth);
     81   else
     82     update(Node[pre].r, Node[o].r, mid + 1, r, kth);
     83 }
     84 
     85 int query(int r1, int r2, int l, int r, int kth) {
     86   if(l >= r) return l;
     87   int lc = Node[Node[r2].l].size - Node[Node[r1].l].size;
     88   int mid = (l + r) >> 1;
     89   if(lc >= kth) {
     90     int ans = query(Node[r1].l, Node[r2].l, l, mid, kth);
     91     return ans;
     92   }
     93   else {
     94     int ans = query(Node[r1].r, Node[r2].r, mid + 1, r, kth - lc);
     95     return ans;
     96   }
     97 }
     98 
     99 int Q(int x, int k) {
    100   int l = num[x], r = mx[x];
    101   return  a[query(root[l - 1], root[r], 1, n, k)].id;
    102 }
    103 
    104 int main() {
    105   int u, v, x, k;
    106   scanf("%d", &n);
    107   for(int i = 1; i <= n; ++ i) scanf("%d", &w[i]);
    108   for(int i = 1; i < n; ++ i) {
    109     scanf("%d%d", &u, &v);
    110     insert(u, v); insert(v, u);
    111   }
    112   dfs();
    113   for(int i = 1; i <= n; ++ i) {
    114     a[i].v = w[seg[i]];
    115     a[i].pos = i;
    116     a[i].id = seg[i];
    117   }
    118   sort(a + 1, a + n + 1);
    119   for(int i = 1; i <= n; ++ i) {
    120     rank[a[i].pos] = i;
    121   }
    122   build(root[0], 1, n);
    123   for(int i = 1; i <= n; ++ i) {
    124     update(root[i - 1], root[i], 1, n, rank[i]);
    125   }
    126   scanf("%d", &m);
    127   for(int i = 1; i <= m; ++ i) {
    128     scanf("%d%d", &x, &k);
    129     printf("%d
    ", Q(x, k));
    130   }
    131   return 0;
    132 }
    人工栈+可持久化线段树
  • 相关阅读:
    react中useContext实现父子组件传值
    react中异步action的使用
    react中redux原理图
    react中antd按需引入+自定义主题
    react中修改antd主题色?
    程序员哀叹工资低:二本计算机毕业,四年前端开发,年包才四十万!薪资真的和学历挂钩吗?
    C++学到什么程度可以面试找工作?
    一个风骚的C语言操作引起的轩然大波!
    如何比较两种截然不同的编程语言的性能!路人甲:这怎么比较?
    为啥码了十年代码,做到了高级工程师,但还是单身?
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5176350.html
Copyright © 2011-2022 走看看