【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* ...
随机推荐
- SpringMVC类型转换器、属性编辑器
对于MVC框架,参数绑定一直觉得是很神奇很方便的一个东西,在参数绑定的过程中利用了属性编辑器.类型转换器 参数绑定流程 参数绑定:把请求中的数据,转化成指定类型的对象,交给处理请求的方法 请求进入到D ...
- iframe高度自适应(同域)
今天解决了iframe高度自适应的问题,不过这只是同域下的页面嵌入,以下是代码: function SetCwinHeight(){ var iframeid = document.getElemen ...
- 【web前端面试题整理08】说说最近几次面试(水)
为什么换工作 换工作简单来讲一般会归纳为钱不够或者人不对,我们团队氛围很不错,所以基本就定位到钱不够了,而我更多是考虑到以后的职业发展,简单说来就是对以后几年的工作有想法,而这种想法实现不一定能在现在 ...
- JS正则表达式(JavaScript regular expression)
RegExp直接量和对象的创建 就像字符串和数字一样,程序中每个取值相同的原始类型直接量均表示相同的值,这是显而易见的.程序运行时每次遇到对象直接量(初始化表达式)诸如{}和[]的时候都会创建新对象. ...
- 应用Apache Axis进行Web Service开发
转自(http://tscjsj.blog.51cto.com/412451/84813) 一.概述 SOAP原意为Simple Object Access Protocol(简单对象访问协议),是一 ...
- 让ABAP开发者愈加轻松的若干快捷键
引言 ABAP是一种和当代编程语言在许多方面有着相当不同的编程语言.ABAP的某些方面可能会让我们奇怪,为什么它会如此复杂?而它的某些方面又是那么杰出,给予了ABAP开发者们比其它任何语言更多的便利. ...
- Atitit 衡量项目的规模
Atitit 衡量项目的规模 1. 预估衡量项目的规模的方法1 1.1. 方法一.Delphi 法1 1.2. 方法二. 类比法1 1.3. 方法三.功能点估计法1 1.4. 方法四.PERT估计法2 ...
- php Zend Opcache,xcache,eAccelerator缓存优化详解(具体根据个人需要选择其一即可,功能都一样切勿重复选择)
载入 XCache 模块 引用 ;; 安装成 zend extension (推荐), 路径一般是 "$extension_dir/xcache.so" zend_extensio ...
- __weak与__block区别,深层理解两者区别
准备工作 首先我定义了一个类 MyObject 继承 NSObject,并添加了一个属性 text,重写了description方法,返回 text 的值.这个主要是因为编译器本身对 NSString ...
- Nodejs安装
1 下载NodeJS https://nodejs.org/download/ 最新版下载地址 # wget https://nodejs.org/dist/v0.12.7/node-v0.12. ...