1146: [CTSC2008]网络管理Network

Time Limit: 50 Sec  Memory Limit: 162 MB
Submit: 3495  Solved: 1032
[Submit][Status][Discuss]

Description

  M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门。为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络。该网络的结构由N个路由器和N-1条高速光缆组成。每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络。该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信。 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略。但是由于路由器老化,在这些路由器上进行数据交换会带来很大的延迟。而两个路由器之间的通信延迟时间则与这两个路由器通信路径上所有路由器中最大的交换延迟时间有关。作为M公司网络部门的一名实习员工,现在要求你编写一个简单的程序来监视公司的网络状况。该程序能够随时更新网络状况的变化信息(路由器数据交换延迟时间的变化),并且根据询问给出两个路由器通信路径上延迟第k大的路由器的延迟时间。【任务】 你的程序从输入文件中读入N个路由器和N-1条光缆的连接信息,每个路由器初始的数据交换延迟时间Ti,以及Q条询问(或状态改变)的信息。并依次处理这Q条询问信息,它们可能是: 1. 由于更新了设备,或者设备出现新的故障,使得某个路由器的数据交换延迟时间发生了变化。 2. 查询某两个路由器a和b之间的路径上延迟第k大的路由器的延迟时间。

Input

  第一行为两个整数N和Q,分别表示路由器总数和询问的总数。第二行有N个整数,第i个数表示编号为i的路由器初始的数据延迟时间Ti。紧接着N-1行,每行包含两个整数x和y。表示有一条光缆连接路由器x和路由器y。紧接着是Q行,每行三个整数k、a、b。如果k=0,则表示路由器a的状态发生了变化,它的数据交换延迟时间由Ta变为b。如果k>0,则表示询问a到b的路径上所经过的所有路由器(包括a和b)中延迟第k大的路由器的延迟时间。注意N,Q<=80000,任意一个路由器在任何时刻都满足延迟时间小于10^8。对于所有询问满足0<=K<=N

Output

  对于每一个第二种询问(k>0),输出一行。包含一个整数为相应的延迟时间。如果路径上的路由器不足k个,则输出信息“invalid request!”(全部小写不包含引号,两个单词之间有一个空格)。

Sample Input

5 5
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

3
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序 + 带修主席树的更多相关文章

  1. P2617 Dynamic Rankings(带修主席树)

    所谓带修主席树,就是用树状数组的方法维护主席树的前缀和 思路 带修主席树的板子 注意数据范围显然要离散化即可 代码 #include <cstdio> #include <cstri ...

  2. 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)

    3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...

  3. 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 ...

  4. BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)

    Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...

  5. bzoj 3551 kruskal重构树dfs序上的主席树

    强制在线 kruskal重构树,每两点间的最大边权即为其lca的点权. 倍增找,dfs序对应区间搞主席树 #include<cstdio> #include<cstring> ...

  6. BZOJ1901 Dynamic Rankings|带修主席树

    题目链接:戳我 其实我并不会做,于是看了题解 我们都知道主席树是利用前缀和记录历史版本来搞区间K大的一种数据结构.不过一般的主席树只能搞定静态区间第K大.如果带修怎么办呢? 想一下...单点修改+区间 ...

  7. BZOJ4771 七彩树(dfs序+树上差分+主席树)

    考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...

  8. 带修主席树 洛谷2617 支持单点更新以及区间kth大查询

    题目链接:https://www.luogu.com.cn/problem/P2617 参考博客:https://blog.csdn.net/dreaming__ldx/article/details ...

  9. [luogu P2617] Dynamic Rankings 带修主席树

    带修改的主席树,其实这种,已经不能算作主席树了,因为这个没有维护可持久化的... 主席树直接带修改的话,由于这种数据结构是可持久化的,那么要相应改动,这个节点以后所有的主席树,这样单次修改,就达到n* ...

随机推荐

  1. SpringMVC类型转换器、属性编辑器

    对于MVC框架,参数绑定一直觉得是很神奇很方便的一个东西,在参数绑定的过程中利用了属性编辑器.类型转换器 参数绑定流程 参数绑定:把请求中的数据,转化成指定类型的对象,交给处理请求的方法 请求进入到D ...

  2. iframe高度自适应(同域)

    今天解决了iframe高度自适应的问题,不过这只是同域下的页面嵌入,以下是代码: function SetCwinHeight(){ var iframeid = document.getElemen ...

  3. 【web前端面试题整理08】说说最近几次面试(水)

    为什么换工作 换工作简单来讲一般会归纳为钱不够或者人不对,我们团队氛围很不错,所以基本就定位到钱不够了,而我更多是考虑到以后的职业发展,简单说来就是对以后几年的工作有想法,而这种想法实现不一定能在现在 ...

  4. JS正则表达式(JavaScript regular expression)

    RegExp直接量和对象的创建 就像字符串和数字一样,程序中每个取值相同的原始类型直接量均表示相同的值,这是显而易见的.程序运行时每次遇到对象直接量(初始化表达式)诸如{}和[]的时候都会创建新对象. ...

  5. 应用Apache Axis进行Web Service开发

    转自(http://tscjsj.blog.51cto.com/412451/84813) 一.概述 SOAP原意为Simple Object Access Protocol(简单对象访问协议),是一 ...

  6. 让ABAP开发者愈加轻松的若干快捷键

    引言 ABAP是一种和当代编程语言在许多方面有着相当不同的编程语言.ABAP的某些方面可能会让我们奇怪,为什么它会如此复杂?而它的某些方面又是那么杰出,给予了ABAP开发者们比其它任何语言更多的便利. ...

  7. Atitit 衡量项目的规模

    Atitit 衡量项目的规模 1. 预估衡量项目的规模的方法1 1.1. 方法一.Delphi 法1 1.2. 方法二. 类比法1 1.3. 方法三.功能点估计法1 1.4. 方法四.PERT估计法2 ...

  8. php Zend Opcache,xcache,eAccelerator缓存优化详解(具体根据个人需要选择其一即可,功能都一样切勿重复选择)

    载入 XCache 模块 引用 ;; 安装成 zend extension (推荐), 路径一般是 "$extension_dir/xcache.so" zend_extensio ...

  9. __weak与__block区别,深层理解两者区别

    准备工作 首先我定义了一个类 MyObject 继承 NSObject,并添加了一个属性 text,重写了description方法,返回 text 的值.这个主要是因为编译器本身对 NSString ...

  10. Nodejs安装

    1 下载NodeJS   https://nodejs.org/download/ 最新版下载地址 # wget https://nodejs.org/dist/v0.12.7/node-v0.12. ...