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

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

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000000
int 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;
}

BZOJ1146——[CTSC2008]网络管理Network的更多相关文章

  1. [BZOJ1146][CTSC2008]网络管理Network

    [BZOJ1146][CTSC2008]网络管理Network 试题描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建 ...

  2. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  3. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

  4. 2019.01.13 bzoj1146: [CTSC2008]网络管理Network(整体二分+树剖)

    传送门 题意简述:给一棵树,支持单点修改,询问路径上两点间第kkk大值. 思路: 读懂题之后立马可以想到序列上带修区间kkk大数的整体二分做法,就是用一个bitbitbit来支持查值. 那么这个题把树 ...

  5. 【树上莫队】【带修莫队】【权值分块】bzoj1146 [CTSC2008]网络管理Network

    #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using ...

  6. 【树链剖分】【函数式权值分块】bzoj1146 [CTSC2008]网络管理Network

    裸题,直接上.复杂度O(n*sqrt(n)*log(n)). //Num[i]表示树中的点i在函数式权值分块中对应的点 //Map[i]表示函数式权值分块中的点i在树中对应的点 #include< ...

  7. 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树

    [BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...

  8. BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submi ...

  9. 【BZOJ-1146】网络管理Network DFS序 + 带修主席树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3495  Solved: 1032[Submi ...

随机推荐

  1. python 模拟登陆,请求包含cookie信息

    需求: 1.通过GET方法,访问URL地址一,传入cookie参数 2.根据地址一返回的uuid,通过POST方法,传入cooki参数 实现思路: 1.理解http的GET和POST差别 (网上有很多 ...

  2. spark操作geoip的domain数据库

    val ipv4 = sc.textFile("hdfs://hbase11:9000/sparkTsData/GeoIP2-Domain-Blocks-IPv4.csv").ma ...

  3. 理解Linux系统/etc/init.d目录和/etc/rc.local脚本

       一.关于/etc/init.d 如果你使用过Linux系统,那么你一定听说过init.d目录.这个目录到底是干嘛的呢?它归根结底只做了一件事情,但这件事情非同小可,是为整个系统做的,因此它非常重 ...

  4. 10月21上午PHP基础

    新建的php文件必须要放在wamp安装目录下的www文件夹里.如果拿到别的地方,php无法运行,将显示错误. <?php?> //嵌入php的方式 <?php //嵌入php方式的开 ...

  5. Java数据库——处理大数据对象

    处理大数据对象 CLOB中可以存储海量文字 BLOB中可以存储海量二进制数据 如果程序中要想处理这样的大对象操作,则必须使用PreparedStatement完成,所有的内容要通过IO流的方式从大文本 ...

  6. Maven概览

    Maven的核心思想,约定由于配置 1 Maven坐标 1.1 本项目的坐标 groupId: 必须.项目组名称,定义当前Maven项目所隶属的实际项目,通常与域名反向一一对应,与Java包名表示方式 ...

  7. ListView 里面嵌套 GridView 遇到的问题及其解决方法。

    我们直接入主题.所有问题例子请参照下图 1,怎样使图片具有点击事件? 答: 解决方法: 在你的BaseAdapter里面不要设置下面这三个东西,然后再设置GridView的onItemClick. g ...

  8. 一段发工资的shell代码

    人事发工资条之前是一个个截图发到我们的邮箱里,看人事妹纸是一个善良而又美丽的姑凉,于是乎写了一段shell代码实现批量发短信至各个手机号.不多说了,上代码,其实很简单,我都不好意思上传,还是记录下吧, ...

  9. C#使用百度API通过IP获取地理位置和坐标

    百度接口相关说明:http://developer.baidu.com/map/ip-location-api.htm 返回是json格式,首先构建相关反系列化类: #region AddressFo ...

  10. [Unity] 精灵动画制作中需要注意的一些问题

    1. 为精灵添加了动画控制器,UpdateMode设置为了Animate Physics,精灵就不受控制了,在游戏中不断的晃动,不受重力影响向下掉等奇葩问题出现了. 解决办法: 此类问题,除掉刚体设置 ...