首页 技术 正文
技术 2022年11月21日
0 收藏 931 点赞 4,302 浏览 3281 个字

1、题目大意:就是在动态的树上路径权值第k大。

2、分析:这个就是树链剖分+树套树

#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;#define M 1000000int Height[M], Top[M], value[M], num[M], Size[M], Fa[M];int ST_tot, tot;int son[M], head[M], Next[M];int n, m;struct Node{    Node *ch[2];    int cnt, num, r, v;    bool operator < (const Node& rhs) const{        return r < rhs.r;    }    int cmp(int x){        if(x == v) return -1;        if(x < v) return 0;        return 1;    }    void maintain(){        cnt = num;        if(ch[0]) cnt += ch[0] -> cnt;        if(ch[1]) cnt += ch[1] -> cnt;    }} *root[2 * M], ft[5 * M];int treap_tot;inline void treap_rotate(Node* &o, int d){    Node* k = o -> ch[d ^ 1];    o -> ch[d ^ 1] = k -> ch[d];    k -> ch[d] = o;    o -> maintain();    k -> maintain();    o = k;    return;}inline void treap_insert(Node* &o, int x){    if(o == NULL){        o = &ft[treap_tot ++];        o -> ch[0] = o -> ch[1] = NULL;        o -> cnt = o -> num = 1;        o -> v = x;        o -> r = rand();    }    else{        int d = o -> cmp(x);        if(d == -1){            o -> num ++;        }        else{            treap_insert(o -> ch[d], x);            if(o < o -> ch[d]) treap_rotate(o, d ^ 1);        }    }    o -> maintain();}inline void treap_remove(Node* &o, int x){    int d = o -> cmp(x);    if(d == -1){        if(o -> num > 1) o -> num --;        else if(o -> ch[0] == NULL) o = o -> ch[1];        else if(o -> ch[1] == NULL) o = o -> ch[0];        else {            int d2;            if(o -> ch[0] > o -> ch[1]) d2 = 1;            else d2 = 0;            treap_rotate(o, d2);            treap_remove(o -> ch[d2], x);        }    }    else treap_remove(o -> ch[d], x);    if(o) o -> maintain();}inline int treap_lessk(Node* &o, int k){    if(o == NULL) return 0;    int d = o -> cmp(k);    if(d == -1){        int ret = 0;        if(o -> ch[0]) ret += o -> ch[0] -> cnt;        return ret;    }    else if(d == 0){        return treap_lessk(o -> ch[0], k);    }    else{        int ss = o -> num;        if(o -> ch[0]) ss += o -> ch[0] -> cnt;        return treap_lessk(o -> ch[1], k) + ss;    }}inline void init(){    Top[1] = 1;    memset(head, -1, sizeof(head));    tot = ST_tot = 0;}inline void add(int l, int r, int o, int x, int y, int z){    if(y != -1) treap_remove(root[o], y);    treap_insert(root[o], z);    if(l == r) {        return;    }    int mid = (l + r) / 2;    if(x <= mid) add(l, mid, 2 * o, x, y, z);    else add(mid + 1, r, 2 * o + 1, x, y, z);}inline int query(int l, int r, int o, int x, int y, int z){    if(x <= l && r <= y) return root[o] -> cnt - treap_lessk(root[o], z);    int ret = 0, mid = (l + r) / 2;    if(x <= mid) ret += query(l, mid, 2 * o, x, y, z);    if(y > mid) ret += query(mid + 1, r, 2 * o + 1, x, y, z);    return ret;}inline void insert(int x, int y){    tot ++;    son[tot] = y;    Next[tot] = head[x];    head[x] = tot;}inline void dfs1(int x, int fa, int height){    Fa[x] = fa;    Height[x] = height;    Size[x] = 1;    for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){        dfs1(son[i], x, height + 1);        Size[x] += Size[son[i]];    }}inline void dfs2(int x, int fa){    ++ ST_tot;    num[x] = ST_tot;    add(1, n, 1, ST_tot, -1, value[x]);    int o = 0, ss = 0;    for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){        if(Size[son[i]] > ss){            ss = Size[son[i]];            o = i;        }    }    if(o != 0){        Top[son[o]] = Top[x];        dfs2(son[o], x);    }    for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa && o != i){        Top[son[i]] = son[i];        dfs2(son[i], x);    }}inline void real_add(int x, int y){    add(1, n, 1, num[x], value[x], y);    value[x] = y;}inline int check(int x, int y, int k){    int ret = 0;    while(Top[x] != Top[y]){        if(Height[Top[x]] < Height[Top[y]]) swap(x, y);        ret += query(1, n, 1, num[Top[x]], num[x], k);        x = Fa[Top[x]];    }    if(Height[x] < Height[y]) swap(x, y);    ret += query(1, n, 1, num[y], num[x], k);    return ret;}inline int real_query(int x, int y, int k){    int l = -1, r = 100000000;    while(l < r){        int mid = (l + r) / 2;        if(mid == l) mid ++;        if(check(x, y, mid) >= k) l = mid;        else r = mid - 1;    }    if(l == -1) return -1;    return l;}int main(){    scanf("%d%d", &n, &m);    init();    for(int i = 1; i <= n; i ++) scanf("%d", &value[i]);    for(int i = 1; i < n; i ++){        int x, y;        scanf("%d%d", &x, &y);        insert(x, y);        insert(y, x);    }    dfs1(1, 0, 1);    dfs2(1, 0);    for(int i = 1; i <= m; i ++){        int k, x, y;        scanf("%d%d%d", &k, &x, &y);        if(k == 0){            real_add(x, y);        }        else if(k > 0){            int qq = real_query(x, y, k);            if(qq == -1){                printf("invalid request!\n");            }            else{                printf("%d\n", qq);            }        }    }    return 0;}

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,031
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,520
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,368
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,148
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,781
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,860