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 ...
随机推荐
- 查看大图 zoomImage
添加引用 <link rel="stylesheet" media="screen" type="text/css" href=&qu ...
- Java中返回参数值的几种状态
Java 中无参无返回值方法的使用 第一步,定义方法 例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 " welcome to imooc. & ...
- 解决WebService 中泛型接口不能序列化问题
本来要定义WebServices 方法返回一泛型接口集合IList,系统提示不能序列化泛型接口集合 1 [WebMethod] 2 public IList<Employ ...
- Js弹出层,弹出框代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- <meta http-equiv = "X-UA-Compatible" cotent = "IE=edge,chrome=1"/>
<meta http-equiv = "X-UA-Compatible" cotent = "IE=edge,chrome=1"/> 制定ie调用哪 ...
- Angular JS 使用的注意事项
标签中ng-app,什么情况需要指定名称,什么时候又不需要呢? 1.ng-app="" <div ng-app="" ng-controller='myC ...
- HTML5 Web Speech API 结合Ext实现浏览器语音识别以及输入
简介 Web Speech API是HTML5技术中的一个提供原生语音识别技术的API,Google Chrome在25版之后开始支持Web Speech API,Google也提供了一个 ...
- 【转】Google推荐的命名规则——Android图片资源
http://blog.csdn.net/yy1300326388/article/details/45443477 1.译 资产类型 前缀 例子 图标 ic_ ic_star.png 启动图标 ic ...
- Vehicle’s communication protocol
http://www.crecorder.com/techInfo/commuProtocols.jsp COMMUNICATION PROTOCOLS A “communication protoc ...
- boost 线程、互斥体、条件变量
1.任何技术都是针对特定场景设计的,也就是说,为了解决某个问题而设计的. 2.考虑下面一种场景:一个小旅馆,只有一个卫生间,有清洁人员,店主人,和旅客.卫生间用完之后,就会自动锁闭,必须取钥匙,才能进 ...