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. [连载]《C#通讯(串口和网络)框架的设计与实现》- 10.宿主程序详细设计

    目       录 第十章           宿主程序详细设计... 2 10.1        配置文件设计... 3 10.2        加载设备驱动... 4 10.3        加载 ...

  2. Hibernnate延迟加载策略(这么详细你还看不懂)

    好久没有认真写过博客了,今天就好好的写一篇吧!!!!!!!!! 当Hibernate 从数据库中加载某个对象(例如:Dept对象)时,如果同时自动加载所有的关联的某个对象(例如:Emp对象),而程序实 ...

  3. NodeJs端口被占用的情况

    在NodeJs运行的时候,我们往往会遇到一个问题:“端口被占用”,这个问题,我们的处理办法有哪些呢? 这里我只介绍一下linux下的方法: 1.使用nodeme(忘记是不是这个啦,回去查下,这个要安装 ...

  4. ReactNative中iOS和Android的style分开设置教程

    reactnative可以编辑iOS程序也可以编辑Android程序, 而且80%的代码都可以重用. 及有些文件是两个系统通用的, 相信大家也都清楚了. 但是也许大家会遇到一些屏幕布局的问题, 最常遇 ...

  5. javaweb项目jsp跳转servlet Error instantiating servlet class 问题

    问题: HTTP Status 500 - Error instantiating servlet class RecommenderServlet type Exception report mes ...

  6. 用css改变默认的checkbox样式

    自己常用的改变checkbox样式的两个方法: 一.利用background用图片代替checkbox效果 缺点:你首先得有一张好看的图片 优点:浏览器兼容性好 <!doctype html&g ...

  7. Redis 与 数据库处理数据的两种模式

    Redis 是一个高性能的key-value数据库. redis的出现,很大程度补偿了memcached这类key-value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用.它提供了Pyt ...

  8. Markdown简介以及常用语法

    Markdown简介以及常用语法 最近发现用markdown记录东西很方便,感觉和emacs的org mode很类似,但是windows下使用emacs不是很方便.特此记录一下markdown常用的语 ...

  9. Programming Learning - Based on Project

    Today when taking a bath I got a good idea that it is an efficient and interesting way to learn a ne ...

  10. 【JS/CSS3】实现带预览图幻灯片效果~

    一.前期准备 1.1 案例分析 适用场景:单例布局1.2 方法论 V视图 HTML+CSS+调试C js实现控制流程D数据 优化扩展 二.代码 结构 <div class="slide ...