BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序
Description
Input
Output
题解:
树套树.
之前做过不带修改的,感觉还挺容易的.
这次是带修改版本,就不能直接在树上建主席树了.
不同的是,我们对 $DFS$ 序建立主席树
考虑到每一次修改一个点,只会对该点的子树到根的路径产生影响.
在 DFS 序中,每个点的子树是一段连续的区间,直接用带修改主席树修改一波即可.
在 DFS 序中,每个点到根节点的路径和就是该点在 DFS 序中的前缀和.
这样进行修改和查询即可.
Code:
#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
#define maxn 200000
#define N 180000
using namespace std;
int n,q, edges,cc,num;
//权值线段树
namespace Seg
{
#define mid ((l+r)>>1)
int rt[maxn],node[10][maxn],cnt[10];
int tot;
struct Node
{
int l,r,w;
}t[maxn*50];
void insert(int &x,int l,int r,int k,int delta)
{
if(!x) x=++tot;
t[x].w+=delta;
if(l==r) return;
if(k<=mid)
insert(t[x].l,l,mid,k,delta);
else
insert(t[x].r,mid+1,r,k,delta);
}
int lowbit(int t)
{
return t & (-t);
}
void update(int pos,int val,int delta)
{
while(pos<=N) insert(rt[pos],1,N,val,delta),pos+=lowbit(pos);
}
int query(int l,int r,int kth)
{
if(l==r) return l;
int sum=0;
for(int i=1;i<=cnt[0];++i) sum+=t[t[node[0][i]].r].w;
for(int i=1;i<=cnt[1];++i) sum+=t[t[node[1][i]].r].w;
for(int i=1;i<=cnt[2];++i) sum-=t[t[node[2][i]].r].w;
for(int i=1;i<=cnt[3];++i) sum-=t[t[node[3][i]].r].w;
if(sum < kth)
{
for(int i=1;i<=cnt[0];++i) node[0][i] = t[node[0][i]].l;
for(int i=1;i<=cnt[1];++i) node[1][i] = t[node[1][i]].l;
for(int i=1;i<=cnt[2];++i) node[2][i] = t[node[2][i]].l;
for(int i=1;i<=cnt[3];++i) node[3][i] = t[node[3][i]].l;
return query(l,mid,kth-sum);
}
else
{
for(int i=1;i<=cnt[0];++i) node[0][i] = t[node[0][i]].r;
for(int i=1;i<=cnt[1];++i) node[1][i] = t[node[1][i]].r;
for(int i=1;i<=cnt[2];++i) node[2][i] = t[node[2][i]].r;
for(int i=1;i<=cnt[3];++i) node[3][i] = t[node[3][i]].r;
return query(mid+1,r,kth);
}
}
// 关键字 : 位置
int Query(int a,int b,int c,int d,int kth)
{
cnt[0]=cnt[1]=cnt[2]=cnt[3]=0;
for(int i=a;i>0;i-=lowbit(i)) node[0][++cnt[0]] = rt[i];
for(int i=b;i>0;i-=lowbit(i)) node[1][++cnt[1]] = rt[i];
for(int i=c;i>0;i-=lowbit(i)) node[2][++cnt[2]] = rt[i];
for(int i=d;i>0;i-=lowbit(i)) node[3][++cnt[3]] = rt[i];
return query(1,N,kth);
}
};
struct Query
{
int opt,a,b;
}Q[maxn];
int hd[maxn],to[maxn],nex[maxn],dfs[maxn],arr[maxn],A[maxn];
int st[maxn],ed[maxn],F[20][maxn],dep[maxn],val[maxn];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
//read and diskreat
void read()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i) scanf("%d",&val[i]),A[++cc]=val[i];
for(int i=1,a,b;i<n;++i)
scanf("%d%d",&a,&b), add(a,b),add(b,a);
for(int i=1;i<=q;++i)
{
scanf("%d%d%d",&Q[i].opt,&Q[i].a,&Q[i].b);
if(Q[i].opt==0) A[++cc]=Q[i].b;
}
sort(A+1,A+1+cc);
for(int i=1;i<=q;++i) if(Q[i].opt==0) Q[i].b=lower_bound(A+1,A+1+cc,Q[i].b)-A;
for(int i=1;i<=n;++i) val[i] = lower_bound(A+1,A+1+cc,val[i])-A;
}
//求dfs序
void DFS(int u,int fa)
{
F[0][u]=fa, dep[u] = dep[fa] + 1;
for(int i=1;i<20;++i) F[i][u]=F[i-1][F[i-1][u]];
dfs[++num]=val[u],st[u]=num;
for(int i=hd[u];i;i=nex[i])
{
if(to[i]==fa) continue;
DFS(to[i],u);
}
ed[u]=num+1;
}
int LCA(int a,int b)
{
if(dep[b]<dep[a]) swap(a,b);
if(dep[a]!=dep[b])
{
for(int i=19;i>=0;--i) if(dep[F[i][b]] >= dep[a]) b = F[i][b];
}
if(a==b) return a;
for(int i=19;i>=0;--i)
{
if(F[i][a]!=F[i][b]) a = F[i][a], b = F[i][b];
}
return F[0][a];
}
int main()
{
// setIO("input");
read();
DFS(1,0);
for(int i = 1;i <= n; ++i)
{
Seg::update(st[i],val[i], 1);
Seg::update(ed[i],val[i], -1);
}
for(int i=1,a,b;i<=q;++i)
{
a = Q[i].a, b = Q[i].b;
if(Q[i].opt==0)
{
Seg::update(st[a], val[a], -1);
Seg::update(ed[a], val[a], 1);
val[a] = b;
Seg::update(st[a],val[a], 1);
Seg::update(ed[a],val[a], -1);
}
if(Q[i].opt>0)
{
int lca = LCA(a,b);
int c = Seg::Query(st[a],st[b],st[lca],st[F[0][lca]],Q[i].opt);
if(c==1)
printf("invalid request!\n");
else
printf("%d\n",A[c]);
}
}
return 0;
}
BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序的更多相关文章
- BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3522 Solved: 1041[Submi ...
- BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )
树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...
- BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 870 Solved: 299[Submit] ...
- [BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
- bzoj 1146 [CTSC2008]网络管理Network
很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...
- BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树
题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...
- 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理
令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...
- 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...
- 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
随机推荐
- log显示error时的堆栈信息理解和分析
error显示的log堆栈信息,是从最深层(最内层)的堆栈信息开始由内向外打印的. error显示的log堆栈信息,是从最深层(最内层)的堆栈信息开始由内向外打印的. error显示的log堆栈信息, ...
- maven打包需要设置main-class的插件写法
maven打包需要设置main-class的插件写法 <build> <plugins> <plugin> <groupId>org.apache.ma ...
- Android 四大组件学习之ContentProvider五
上几节学习了ContentProvider的实际用途,读取短信.插入短信,读取联系人.插入联系人等. 本节课在学习ContentProvider的观察者. 在生活中有第三方的软件.比方什么短信软件.此 ...
- poj 1068 Parencodings(模拟)
转载请注明出处:viewmode=contents">http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://poj ...
- [odroid-pc] ubuntu12.04 android4.0移植到odroid-pc过程
參考:http://blog.csdn.net/sunnybeike/article/details/8098349 odroid prebuilt版 img下载地址:tag=ODROID-PC&q ...
- Android:制作Update.zip升级包 【转】
本文转载自:http://zwkufo.blog.163.com/blog/static/2588251201382293049118/ 很多时候厂商或者三方提供的ROM并不能满足需求,比如系统自带软 ...
- C# Path 有关于文件路径获取的问题 的方法
string Current = Directory.GetCurrentDirectory();//获取当前根目录 //private string strFilePath = Applicatio ...
- Python 下的数据结构实现
既然采用了 Python 编程语言实现数据结构,就要充分发挥 Python 语言的语法特性. 参考<Python 算法教程><数据结构与算法 -- Python 语言描述>: ...
- 【POJ 1964】 City Game
[题目链接] http://poj.org/problem?id=1964 [算法] 记f[i]表示第i行最多向上延伸的行数 然后,对于每一行,我们用单调栈计算出这一行向上延伸的最大矩形面积,取最大值 ...
- .sh文件 编写格式
http://blog.sina.com.cn/s/blog_54f82cc201010hfz.html 介绍: 1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号# ...