BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树
1146: [CTSC2008]网络管理Network
Time Limit: 50 Sec Memory Limit: 162 MB
Submit: 870 Solved: 299
[Submit][Status]
Description
Input
Output
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; const int MAXN = 400005;
const int MAXM = 2500005;
const int INF = 1e8+5; int sz[MAXN],son[MAXN],dep[MAXN],top[MAXN],fa[MAXN],tid[MAXN],tim;
bool use[MAXN];
int val[MAXN];
int po[MAXN],tol;
int now; struct segTree{
int root;
int l,r,val;
inline int mid(){
return (l+r)>>1;
}
}tree[MAXN]; struct Edge{
int y,next;
}edge[MAXN]; inline void add(int x,int y){
edge[++tol].y = y;
edge[tol].next = po[x];
po[x] = tol;
} // splay部分
struct node{
int ch[MAXM][2],sz[MAXM],val[MAXM],fa[MAXM];
int tot; // 初始化根 ok
inline void init(int &x){
newNode(x,0,-1);
newNode(ch[x][1],x,INF+10);//两个虚拟节点
update(ch[x][1]);
update(x);
} // 新的节点 ok
inline void newNode(int &x,int y,int c){
x = ++ tot;
sz[x] = 1;
ch[x][0] = ch[x][1] = 0;
val[x] = c;
fa[x] = y;
} // 更新 ok
inline void update(int x){
if(!x)return;
sz[x] = sz[ ch[x][0] ]+sz[ ch[x][1] ]+1;
} // 旋转 ok
inline int sgn(int x){
return ch[ fa[x] ][1] == x;
}
inline void setc(int y,int d,int x){
ch[y][d] = x;
fa[x] = y;
}
inline void rot(int x,int d){
int y = fa[x];
int z = fa[y];
setc(y,!d,ch[x][d]);
if(z)setc(z,sgn(y),x);
fa[x] = z;
setc(x,d,y);
update(y);
} // splay操作 ok
inline void splay(int x,int goal=0){
if(!x)return;
while(fa[x]!=goal){
int y = fa[x];
int z = fa[y];
if(z==goal){
rot(x,!sgn(x));
break;
}else if(ch[z][0]==y){
ch[y][0]==x ? rot(y,1) : rot(x,0);
rot(x,1);
}else{
ch[y][1]==x? rot(y,0) : rot(x,1);
rot(x,0);
}
}
update(x);
if(!goal)tree[now].root = x;
} // 得到第k大元素 ok
inline int getKth(int x,int k){
while(x){
if(sz[ ch[x][0] ]+1==k)
return x;
else if( sz[ ch[x][0] ]+1>k )
x = ch[x][0];
else{
k -= sz[ ch[x][0] ]+1;
x = ch[x][1];
}
}
return x;
} // 得到值c得排名 ok
inline int getSz(int c){
int x = tree[now].root;
int ans = 0;
while(x){
if(val[x]<=c){
ans += sz[ ch[x][0] ]+1;
x = ch[x][1];
}else
x = ch[x][0];
}
return ans;
} // 得到比c值大的数的个数 ok
inline int getMax(int c){
int x = tree[now].root;
int ans = 0;
while(x){
if(val[x]>=c){
ans += sz[ ch[x][1] ]+1;
x = ch[x][0];
}else
x = ch[x][1];
}
return ans;
} // 插入
inline void ins(int c){
int k = getSz(c); splay( getKth(tree[now].root,k),0 );
splay( getKth(tree[now].root,k+1),tree[now].root ); int root = tree[now].root;
newNode( ch[ ch[root][1] ][0] ,ch[root][1] , c );
update(ch[root][1]);
update(root);
} // 删除,保证有元素c
inline void del(int c){
int k = getSz(c); splay( getKth(tree[now].root,k-1),0 );
splay( getKth(tree[now].root,k+1),tree[now].root ); val[ch[ ch[tree[now].root][1] ][0]] = fa[ ch[ ch[tree[now].root][1] ][0] ] = 0;
ch[ ch[tree[now].root][1] ][0] = 0; update( ch[tree[now].root][1] );
update(tree[now].root);
}
}sp; // 树链剖分部分 ok
void dfsFind(int x,int pa,int depth){
dep[x] = depth;
fa[x] = pa;
sz[x] = 1;
son[x] = 0;
use[x] = true;
for(int i=po[x];i;i=edge[i].next){
int y = edge[i].y;
if(use[y])continue;
dfsFind(y,x,depth+1);
sz[x] += sz[y];
if(sz[y]>sz[ son[x] ])
son[x] = y;
}
} void dfsCon(int x,int pa){
use[x] = true;
top[x] = pa;
tid[x] = ++ tim;
if(son[x])dfsCon(son[x],pa);
for(int i=po[x];i;i=edge[i].next){
int y = edge[i].y;
if(use[y])continue;
dfsCon(y,y);
}
} // 线段树部分
// 建树
void build(int l,int r,int rt){
tree[rt].l = l;
tree[rt].r = r;
if(l==r)
return;
int mid = (l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
} // 修改,把原来的del删除,插入新值c
void modify(int pos,int c,int del,int rt){
now = rt;
if(del!=-1)sp.del( del ); if(!tree[rt].root)
sp.init(tree[rt].root);
sp.ins( c ); if(tree[rt].l==tree[rt].r)
return;
int mid = tree[rt].mid();
if(pos<=mid)
modify(pos,c,del,rt<<1);
else
modify(pos,c,del,rt<<1|1);
} // 在区间[l,r]中查询比c大的数的个数
int ask(int l,int r,int c,int rt){
now = rt;
if(tree[rt].l==l&&tree[rt].r==r)
return sp.getMax( c )-1;
int mid = tree[rt].mid();
if(r<=mid)
return ask(l,r,c,rt<<1);
else if(l>mid)
return ask(l,r,c,rt<<1|1);
else
return ask(l,mid,c,rt<<1)+ask(mid+1,r,c,rt<<1|1);
} inline int cc(int k,int a,int b,int mid){
int ans = 0;
while(top[a]!=top[b]){ // 新型lca求法
if( dep[ top[a] ] < dep[ top[b] ] )
swap(a,b);
ans += ask( tid[ top[a] ] , tid[a] , mid , 1 );
a = fa[ top[a] ];
}
if(dep[a]>dep[b])
swap(a,b);
ans += ask(tid[a],tid[b],mid,1);
return ans;
} int main(){ #ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif int n,m,x,y,k;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++)
scanf("%d",&val[i]); memset(po,0,sizeof(po));
tol = 1;
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
} // 树链剖分
memset(use,false,sizeof(use));
dfsFind(1,1,1); memset(use,false,sizeof(use));
tim = 0;
dfsCon(1,1); // 建立线段树
build(1,n,1);
for(int i=1;i<=n;i++)
modify(tid[i],val[i],-1,1); while(m--){
scanf("%d%d%d",&k,&x,&y);
if(!k){
modify( tid[x],y,val[x],1 );
val[x] = y;
}else{
int ans = -1;
int l = 0 , r = INF;
while(l<=r){
int mid = (l+r)>>1;
int tmp = cc(k,x,y,mid);
if(tmp>=k){
ans = mid;
l = mid+1;
}else
r = mid-1;
}
if(ans==-1)
puts("invalid request!");
else
printf("%d\n",ans);
}
}
}
return 0;
}
BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树的更多相关文章
- BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3522 Solved: 1041[Submi ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
随机推荐
- Innodb的事务与日志 & JTA事务
InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的 通过 行多版本控制 MyISAM Innodb 事物支持 : 不支持 ...
- SQL函数集合
1. PATINDEX ( '%pattern%' , expression ) 返回pattern字符串在表达式expression里第一次出现的位置,起始值从1开始算. pattern字符串在ex ...
- ngTbale假分页实现排序、搜索、导出CSV等功能
一. ngTable功能简化 使用ngTable经常有分页,排序,过滤等功能,实现诸多功能较为麻烦.为了方便开发过程,可以抽取一些table共同点写一个公有方法. 注意: 1. 由于很多特别的需求,可 ...
- 利用css中的border生成三角,兼容包括IE6的主流浏览器
1.生成四个不同颜色方向的梯形 #ladder{ width:20px; height:20px; border:10px solid; border-color:#ff3300 #0000ff #3 ...
- PowerShell管理Exchange
#添加Exchange管理单元get-pssnapin -registeredadd-pssnapin microsoft.exchange* #启用邮箱账号(需要域管理员权限,因为需要将某些属性写入 ...
- HDU 5573 Binary Tree 构造
Binary Tree 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5573 Description The Old Frog King lives ...
- Codeforces Round #310 (Div. 1) A. Case of Matryoshkas 水题
C. String Manipulation 1.0 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contes ...
- uoj #118. 【UR #8】赴京赶考 水题
#118. [UR #8]赴京赶考 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/118 Description ...
- [连载]JavaScript讲义(05)--- 数据处理
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamFja2ZydWVk/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...
- 视频流服务器配置[windows平台][转]
视频流服务器配置[windows平台] 搭建一个Flv视频播放服务器 作者:笨小孩 发布于:2013-9-1 20:18 分类:环境架设 IIS,Apache,Nginx环境都可以很好的支持视频的播放 ...