树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. 时间复杂度O(N*log^3(N))

----------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
 
using namespace std;
 
#define h(v) (lower_bound(H, H + n, v) - H + 1)
 
const int maxn = 80009;
 
inline int read() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ret = 0;
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
int N, Q, w[maxn], seq[maxn], H[maxn << 1], n;
int top[maxn], fa[maxn], sz[maxn], ch[maxn], dep[maxn], Top;
int Id[maxn], Idn;
 
struct edge {
int to;
edge* next;
} E[maxn << 1], *Pt = E, *head[maxn];
 
inline void AddEdge(int u, int v) {
Pt->to = v;
Pt->next = head[u];
head[u] = Pt++;
}
 
struct O {
int t, a, b;
inline void Read() {
t = read(), a = read() - 1, b = read();
if(t) b--;
}
} o[maxn];
 
void Init() {
N = read(), Q = read();
for(n = 0; n < N; n++)
H[n] = w[n] = read();
for(int i = 1; i < N; i++) {
int u = read() - 1, v = read() - 1;
AddEdge(u, v);
AddEdge(v, u);
}
for(int i = 0; i < Q; i++) {
o[i].Read();
if(!o[i].t)
H[n++] = o[i].b;
}
sort(H, H + n);
n = unique(H, H + n) - H;
}
 
struct Node {
Node *lc, *rc;
int v;
Node() : v(0) {
}
} pool[5000000], *pt, *Null, *Root[maxn], *V[maxn];
 
void Init_sgt() {
pt = pool;
Null = pt++;
Null->lc = Null->rc = Null;
Null->v = 0;
}
 
int Pos, Val;
 
Node* Modify(Node* t, int l, int r) {
if(t->v + Val == 0)
return Null;
if(t->v == Val) { 
if(l == r) return t;
int m = (l + r) >> 1;
if(Pos <= m) {
t->lc = Modify(t->lc, l, m);
t->rc = Null;
} else {
t->lc = Null;
t->rc = Modify(t->rc, m + 1, r);
}
return t;
} else {
Node* o = pt++;
o->v = t->v + Val;
int m = (l + r) >> 1;
if(Pos <= m) {
o->lc = Modify(t->lc, l, m);
o->rc = t->rc;
} else {
o->lc = t->lc;
o->rc = Modify(t->rc, m + 1, r);
}
return o;
}
}
 
Node* Add(Node* t, int l, int r) {
Node* o = pt++;
o->v = t->v + Val;
if(l != r) {
int m = (l + r) >> 1;
if(Pos <= m) {
o->lc = Add(t->lc, l, m);
o->rc = t->rc;
} else {
o->lc = t->lc;
o->rc = Add(t->rc, m + 1, r);
}
}
return o;
}
 
void DFS(int x) {
sz[x] = 1;
ch[x] = -1;
for(edge* e = head[x]; e; e = e->next) if(e->to != fa[x]) {
dep[e->to] = dep[x] + 1;
fa[e->to] = x;
DFS(e->to);
sz[x] += sz[e->to];
if(ch[x] == -1 || sz[ch[x]] < sz[e->to])
ch[x] = e->to;
}
}
 
void dfs(int x) {
seq[Id[x] = ++Idn] = x;
top[x] = Top;
if(~ch[x]) dfs(ch[x]);
for(edge* e = head[x]; e; e = e->next)
if(e->to != fa[x] && e->to != ch[x]) dfs(Top = e->to);
}
 
void Init_slpf() {
fa[0] = -1;
dep[0] = 0;
DFS(0);
Idn = 0;
dfs(0);
}
 
void Build() {
Init_sgt();
Root[0] = V[0] = Null;
Val = 1;
for(int i = 1; i <= N; i++) {
Pos = h(w[seq[i]]);
Root[i] = Add(Root[i - 1], 1, n);
V[i] = Null;
}
}
 
Node *L[500], *R[500];
 
void Work() {
int Ln, Rn;
for(int i = 0; i < Q; i++) {
if(o[i].t) {
int x = o[i].a, y = o[i].b, size = 0;
Ln = Rn = 0;
for(; top[x] != top[y]; x = fa[top[x]]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
size += dep[x] - dep[top[x]] + 1;
L[Ln++] = Root[Id[top[x]] - 1];
R[Rn++] = Root[Id[x]];
for(int l = Id[top[x]] - 1; l; l -= l & -l)
L[Ln++] = V[l];
for(int r = Id[x]; r; r -= r & -r)
R[Rn++] = V[r];
}
if(dep[x] > dep[y]) swap(x, y);
size += dep[y] - dep[x] + 1;
L[Ln++] = Root[Id[x] - 1];
R[Rn++] = Root[Id[y]];
for(int l = Id[x] - 1; l; l -= l & -l)
L[Ln++] = V[l];
for(int r = Id[y]; r; r -= r & -r)
R[Rn++] = V[r];
if(size < o[i].t) {
puts("invalid request!");
continue;
} else 
o[i].t = size - o[i].t + 1;
int l = 1, r = n;
while(l < r) {
int m = (l + r) >> 1, cnt = 0;
for(int j = 0; j < Ln; j++)
cnt -= L[j]->lc->v;
for(int j = 0; j < Rn; j++)
cnt += R[j]->lc->v;
if(cnt >= o[i].t) {
for(int j = 0; j < Ln; j++)
L[j] = L[j]->lc;
for(int j = 0; j < Rn; j++)
R[j] = R[j]->lc;
r = m;
} else {
o[i].t -= cnt;
for(int j = 0; j < Ln; j++)
L[j] = L[j]->rc;
for(int j = 0; j < Rn; j++)
R[j] = R[j]->rc;
l = m + 1;
}
}
printf("%d\n", H[l - 1]);
} else {
Pos = h(w[seq[Id[o[i].a]]]), Val = -1;
for(int x = Id[o[i].a]; x <= N; x += x & -x)
V[x] = Add(V[x], 1, n);
Pos = h(w[seq[Id[o[i].a]]] = o[i].b), Val = 1;
for(int x = Id[o[i].a]; x <= N; x += x & -x)
V[x] = Add(V[x], 1, n);
}
}
}
 
int main() {
Init();
Init_slpf();
Build();
Work();
return 0;
}

----------------------------------------------------------------------------

1146: [CTSC2008]网络管理Network

Time Limit: 50 Sec  Memory Limit: 162 MB
Submit: 2943  Solved: 859
[Submit][Status][Discuss]

Description

M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是: 1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。 2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

Input

第一行为两个整数N和Q,分别表示路由器总数和询问的总数。第二行有N个整数,第i个数表示编号为i的路由器初始的数据延迟时间Ti。紧接着N-1行,每行包含两个整数x和y。表示有一条光缆连接路由器x和路由器y。紧接着是Q行,每行三个整数k、a、b。如果k=0,则表示路由器a的状态发生了变化,它的数据交换延迟时间由Ta变为b。如果k>0,则表示询问a到b的路径上所经过的所有路由器(包括a和b)中延迟第k大的路由器的延迟时间。注意a可以等于b,此时路径上只有一个路由器。

Output

对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。如果路径上的路由器不足k个,则输出信息“invalid request!”(全部小写不包含引号,两个单词之间有一个空格)。

Sample Input

5 5
5 1 2 3 4
3 1
2 1
4 3
5 3
2 4 5
0 1 2
2 2 3
2 1 4
3 3 5

Sample Output

3
2
2
invalid request!

HINT

10% 测试数据满足N<=8000,Q<=3000,

40% 测试数据满足所有询问中1<=K<=5 。即路由器的延迟时间不会发生变化。

100% 测试数据满足N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N 。

Source

BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )的更多相关文章

  1. [BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  2. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  3. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  4. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  5. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  6. bzoj1901--树状数组套主席树

    树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...

  7. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  8. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  9. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  10. [COGS257]动态排名系统 树状数组套主席树

    257. 动态排名系统 时间限制:5 s   内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...

随机推荐

  1. LDT自己定义启动模拟器

    近期使用LUA开发手游,团队里大神自研了个框架,底层C++渲染,上层LUA处理逻辑. LUA的IDE选择LDT,不爽的是它不能自己主动启动模拟器,看过COCOSIDE能自启动,于是我想改造下LDT让它 ...

  2. React系列(一):React入门

    React简介 1.由来 React是有Facebook开发出来用于构建前端界面的JS组件库,由于其背后的强大背景,使得这款库在技术开发上完全没有问题. 2.React的优势 解决大规模项目开发中数据 ...

  3. 检索算法 -- 数据结构与算法的javascript描述 第13章

    检索算法-如何在列表中查找特定的值. 顺序查找 从列表的第一个元素开始对列表元素逐个进行判断,直到找到了想要的结果,它属于暴力查找技巧的一种,在执行查找时可能会访问到数据结构里的所有元素. 代码: / ...

  4. sqlserver查询某一字段重复超5次的所有记录

    用的sqlserver2008 r2. SELECT  * FROM t_class WHERE id IN (SELECT  id FROM (SELECT  ROW_NUMBER() OVER ( ...

  5. 常用封装--Date篇--获取格式化的日期对象

    虽然日期对象可以使用new Date()来获取,但是对于其格式却必须进行相应的转换,才能成为开发者想要的格式. 这里提供了一个封装的方法,通过结合正则表达式的使用,达到了可以对时间对象进行处理,生成多 ...

  6. CSS3 Pie工具可以让IE6至IE8版本实现大多数的CSS3修饰特性,如圆角、阴影、渐变等

    css3 pie使用方法: <!doctype html> <html lang="en"> <head> <meta charset=& ...

  7. nginx的配置说明

    #定义Nginx运行的用户和用户组user www www; #nginx进程数,建议设置为等于CPU总核心数.worker_processes 8; #全局错误日志定义类型,[ debug | in ...

  8. 简洁的PHP操作SQLite类

    SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了. ...

  9. hdu 1695 GCD 容斥+欧拉函数

    题目链接 求 $ x\in[1, a] , y \in [1, b] $ 内 \(gcd(x, y) = k\)的(x, y)的对数. 问题等价于$ x\in[1, a/k] , y \in [1, ...

  10. centos6.5编译android-2.2_froyo的几个问题jdk,gcc,arm-gcc

    1.gcc降级 因为之前用QT升级了gcc到4.8.0,现在编译安卓又要降到4.4.6 我这边是直接下的gcc-4.4.6源码安装的 gcc源码安装包下载: ftp://ftp.mpi-sb.mpg. ...