这题的复杂度可以到达惊人的\(\log^4\)据说还能跑过去(差点没吓死我

直接二分+树剖树套树(\(n \log^4 n\))

一个\(\log\)也不少的4\(\log\)

但是我有个\(\log^3\)的树剖上面整体二分+线段树的做法

不过据说有个\(\log\)做法,我不会,反正我菜就是了

然后的话 就直接考虑个消除贡献…然而并不需要排序

权值线段树 就可以了

每次添加修改就

        if(! op) {
int y = read() , z = read() ;
Q[++ tot] = { 0 , -1 , val[y] , y , 1 } ; val[y] = z ;
Q[++ tot] = { 0 , 1 , val[y] , y , 1 } ; b[++ len] = z ;
} else {
int y = read() , z = read() ; Q[++ tot] = { y , z , op , ++ pos , 2} ;
}

然后就成功完成了打消贡献以及添加贡献

然后整体二分板子即可

#include <bits/stdc++.h>
#define int long long
#define rep(a , b , c) for(int a = b ; a <= c ; ++ a)
#define Rep(a , b , c) for(int a = b ; a >= c ; -- a)
#define go(u) for(int i = G.head[u] , v = G.to[i] , w = G.dis[i] ; i ; v = G.to[i = G.nxt[i]] , w = G.dis[i])
using namespace std ;
using ll = long long ;
using pii = pair < int , int > ;
using vi = vector < int > ;
int read() {
int x = 0 ; bool f = 1 ; char c = getchar() ;
while(c < 48 || c > 57) {
if(c == '-') f = 0 ;
c = getchar() ;
}
while(c > 47 && c < 58) {
x = (x << 1) + (x << 3) + (c & 15) ;
c = getchar() ;
}
return f ? x : -x ;
}
template <class T> void print(T x , char c = '\n') {
static char st[100] ; int stp = 0 ;
if(! x) putchar('0') ; if(x < 0) x = -x , putchar('-') ;
while(x) st[++ stp] = x % 10 ^ 48 , x /= 10 ;
while(stp) putchar(st[stp --]) ; putchar(c) ;
}
template <class T> void cmax(T & x , T y) { x < y ? x = y : 0 ; }
template <class T> void cmin(T & x , T y) { x > y ? x = y : 0 ; }
const int _N = 1e6 + 10 ;
struct Group {
int head[_N] , nxt[_N << 1] , to[_N] , dis[_N] , cnt = 1 ;
Group () { memset(head , 0 , sizeof(head)) ; }
void add(int u , int v , int w = 1) { nxt[++ cnt] = head[u] ; to[cnt] = v ; dis[cnt] = w ; head[u] = cnt ; }
} ;
const int N = 5e5 + 10 ;
typedef int arr[N] ;
Group G ;
int n , q , len = 0 , val[N] , b[N << 1] ;
arr fa , d , son , sz ;
void dfs(int u) {
sz[u] = 1 ; go(u) if(v ^ fa[u]) {
fa[v] = u , d[v] = d[u] + 1 , dfs(v) , sz[u] += sz[v] ;
if(sz[v] > sz[son[u]]) son[u] = v ;
}
}
arr top , id ;
int idx = 0 ;
void dfs(int u , int t) {
top[u] = t ;
id[u] = ++ idx ;
if(son[u]) dfs(son[u] , t) ;
go(u) if(v ^ fa[u] && v ^ son[u]) dfs(v , v) ;
}
struct Seg {
int sum[N << 2] ;
void change(int l , int r , int rt , int pos , int val) {
if(l == r) { sum[rt] += val ; return ; }
int mid = l + r >> 1 ;
if(pos <= mid) change(l , mid , rt << 1 , pos , val) ;
else change(mid + 1 , r , rt << 1 | 1 , pos , val) ;
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1] ;
}
int query(int a , int b , int l , int r , int rt) {
if(a <= l && r <= b) return sum[rt] ;
int mid = l + r >> 1 , ans = 0 ;
if(a <= mid) ans += query(a , b , l , mid , rt << 1) ;
if(b > mid) ans += query(a , b , mid + 1 , r , rt << 1 | 1) ;
return ans ;
}
} t ;
int query_range(int x , int y) {
int ans = 0 ;
while(top[x] != top[y]) { if(d[top[x]] < d[top[y]]) swap(x , y) ; ans += t.query(id[top[x]] , id[x] , 1 , n , 1) ; x = fa[top[x]] ; }
if(d[x] > d[y]) swap(x , y) ; ans += t.query(id[x] , id[y] , 1 , n , 1) ;
return ans ;
}
struct Query {
int x , y , k , id , type ;
} Q[N] , q1[N] , q2[N] ;
int tot = 0 , num = 0 , pos = 0 ;
arr ans ;
void solve(int L , int R , int l , int r) {
if(L > R) return ;
if(l == r) {
rep(i , L , R) if(Q[i].type == 2) ans[Q[i].id] = l ; return ;
}
int mid = l + r >> 1 , cnt1 = 0 , cnt2 = 0 ;
rep(i , L , R) {
if(Q[i].type == 1) {
if(Q[i].k > mid) {
t.change(1 , n , 1 , id[Q[i].id] , Q[i].y) ; q2[++ cnt2] = Q[i] ;
} else q1[++ cnt1] = Q[i] ;
} else {
int res = query_range(Q[i].x , Q[i].y) ;
if(res >= Q[i].k) q2[++ cnt2] = Q[i] ;
else { Q[i].k -= res ; q1[++ cnt1] = Q[i] ; }
}
}
rep(i , 1 , cnt2) if(q2[i].type == 1) t.change(1 , n , 1 , id[q2[i].id] , -q2[i].y) ;
rep(i , 1 , cnt1) Q[L + i - 1] = q1[i] ; rep(i , 1 , cnt2) Q[L + cnt1 + i - 1] = q2[i] ;
solve(L , L + cnt1 - 1 , l , mid) ; solve(L + cnt1 , R , mid + 1 , r) ;
}
signed main() {
n = read() ; q = read() ;
rep(i , 1 , n) { val[i] = read() ; Q[++ tot] = { 0 , 1 , val[i] , i , 1 } ; b[++ len] = val[i] ; }
rep(i , 2 , n) { int x = read() , y = read() ; G.add(x , y) ; G.add(y , x) ; }
dfs(1) ; dfs(1 , 1) ;
rep(i , 1 , q) {
int op = read() ;
if(! op) {
int y = read() , z = read() ;
Q[++ tot] = { 0 , -1 , val[y] , y , 1 } ; val[y] = z ;
Q[++ tot] = { 0 , 1 , val[y] , y , 1 } ; b[++ len] = z ;
} else {
int y = read() , z = read() ; Q[++ tot] = { y , z , op , ++ pos , 2} ;
}
}
sort(b + 1 , b + len + 1) , len = unique(b + 1 , b + len + 1) - b - 1 ;
rep(i , 1 , tot) if(Q[i].type != 2) Q[i].k = lower_bound(b + 1 , b + len + 1 , Q[i].k) - b ;
solve(1 , tot , 0 , len + 1) ;
rep(i , 1 , pos) {
if(! ans[i]) puts("invalid request!") ;
else print(b[ans[i]]) ;
}
return 0 ;
}

[CTSC2008]网络管理 [树剖+整体二分]的更多相关文章

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

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

  2. P4175 [CTSC2008]网络管理 树剖+树套树

    $ \color{#0066ff}{ 题目描述 }$ M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 ...

  3. bzoj 1146 网络管理Network (CDQ 整体二分 + 树刨)

    题目传送门 题意:求树上路径可修改的第k大值是多少. 题解:CDQ整体二分+树刨. 每一个位置上的数都会有一段持续区间 根据CDQ拆的思维,可以将这个数拆成出现的时间点和消失的时间点. 然后通过整体二 ...

  4. BZOJ4538 HNOI2016网络(树链剖分+线段树+堆/整体二分+树上差分)

    某两个点间的请求只对不在这条路径上的询问有影响.那么容易想到每次修改除该路径上的所有点的答案.对每个点建个两个堆,其中一个用来删除,线段树维护即可.由于一条路径在树剖后的dfs序中是log个区间,所以 ...

  5. 洛谷P4332 [SHOI2014]三叉神经树(LCT,树剖,二分查找,拓扑排序)

    洛谷题目传送门 你谷无题解于是来补一发 随便百度题解,发现了不少诸如树剖\(log^3\)LCT\(log^2\)的可怕描述...... 于是来想想怎么利用题目的性质,把复杂度降下来. 首先,每个点的 ...

  6. 【bzoj2738】矩阵乘法 整体二分+二维树状数组

    题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入 第一行两个数N,Q,表示矩阵大小和询问组数:接下来N行N列一共N*N个数,表示这个矩阵:再接下来Q行每行5个数 ...

  7. 整体二分--BZOJ1901: Zju2112 Dynamic Rankings

    n<=10000个数有m<=10000个操作,1.询问一个区间的第k小的数:2.单点修改. 带修主席树. 整体二分. 整体二分的必要条件: #include<string.h> ...

  8. [CTSC2008]网络管理(整体二分+树剖+树状数组)

    一道经典的带修改树链第 \(k\) 大的问题. 我只想出三个 \(\log\) 的解法... 整体二分+树剖+树状数组. 那不是暴力随便踩的吗??? 不过跑得挺快的. \(Code\ Below:\) ...

  9. 【BZOJ1146】【CTSC2008】网络管理 [整体二分]

    网络管理 Time Limit: 50 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司,在 ...

随机推荐

  1. python学习(4)循环语句

    循环语句主要有两个,一个是 while :一个是for in range() 以案例来说明: 写一个猜数字的游戏,正确的数字等于38.如果数字等于38,则提示正确,然后结束:如果数字大于38则提示大了 ...

  2. FastDFS 配置文件 tracker.conf

    FastDFS 版本5.05 配置文件分为三部分   控制器:tracker.conf存储器:storage.conf 客户端:client.conf 文件位置:/etc/fdfs 基本配置(基础配置 ...

  3. 在Linux实例上自动安装并运行VNC Server

    #!/bin/bash ######################################### #Function: install vnc server #Usage: bash ins ...

  4. 赛狗日源码分享 《Head First C#》第三版

    目录 前言 效果展示 步骤 熟读任务说明 搭界面 开始代码 From.cs Greyhound.cs Guy.cs Bet.cs 写在后面的话 本次遇见的一些问题 关于优化 可以设定狗的特性 去掉Be ...

  5. Java基于过滤器进行重定向不成功问题的兩種解決辦法,以及基於JSF的ajax重定向解決辦法

    我创建了一个过滤器,只要用户没有登陆就不能连接到主界面,但是在doFilter方法中用重定向在前端跳转页面不成功. 原因:由于我的登陆界面是基于ajax请求的,而ajax默认不支持重定向,他只能局部更 ...

  6. Linux安装Redis,在测试阶段即make test出现“You need tcl 8.5 or newer in order to run the Redis test”问题解决方案

    Linux安装Redis,在测试阶段即make test出现"You need tcl 8.5 or newer in order to run the Redis test"问题 ...

  7. 传智播客C++视频学习笔记(5)

    #include <iostream> using namespace std; void swapInt(int& a, int& b) { int temp = a; ...

  8. 图解Java设计模式之设计模式面试题

    图解Java设计模式之设计模式面试题 1.1 Java设计模式内容介绍 1.1.1 先看几个经典的面试题 1.1.2 设计模式的重要性 1.1 Java设计模式内容介绍 1.1.1 先看几个经典的面试 ...

  9. 浏览器中常见的html语义化标签

    html标签默认在浏览器中展示的样式,html标签的用途:语义化(明白每个标签的用途,在什么情况下使用此标签合理);标签语义化好处:1.更容易被搜索引擎收录2.更容易让屏幕阅读器读出网页内容. 网页上 ...

  10. SharePoint PowerShell SendEmail

    前言 最近碰到这样一个需求,用户需要个简单的定时邮件提醒,就是抓取SharePoint某个列表里的值,然后作为邮件地址/邮件主题/邮件内容发送出去. 自己想了想,既然用户要求每天定时发送,那么肯定是任 ...