题目描述

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

输入

第一行为两个整数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

输出

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

样例输入

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

样例输出

3
2
2
invalid request!
 
题目要求路径第k大,那么就要维护出路径每个点的权值。
我们不妨在树上每个点开一棵权值线段树来存这个点到根路径上每个点的权值。
查询时将路径以两点LCA分成两部分,即对于路径(x,y),只要将x点的线段树+y点的线段树-lca点的线段树-lca父节点的线段树就能得到路径上点的权值。
可以发现一个点的权值被子树内所有点上的线段树存储,在树上无法修改,那么可以转化到出栈入栈序上。
对于单点修改,在出栈入栈序上就是对于一个区间每个点的线段树都修改,而查询时是单点的线段树查询。
那么我们可以差分一下,在修改点入栈时刻加入出栈时刻删除,这样就变成了单点修改前缀查询。
直接树状数组套权值线段树即可。(套主席树和套权值线段树没啥区别,就是套权值线段树内存小点)
做这题之前建议先做->BZOJ1901
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int s[80050];
int t[80050];
int num;
int cnt;
int tot;
int a[80050];
int head[80050];
int to[160050];
int next[160050];
int sum[20000050];
int ls[20000050];
int rs[20000050];
int root[160050];
int f[80050];
int size[80010];
int top[80010];
int son[80010];
int d[80050];
int s1[80050];
int s2[80050];
int s3[80050];
int s4[80050];
int opt;
int x,y;
void addd(int x,int y)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void dfs2(int x,int t)
{
top[x]=t;
if(son[x])
{
dfs2(son[x],t);
}
for(int i=head[x];i;i=next[i])
{
if(to[i]!=f[x]&&to[i]!=son[x])
{
dfs2(to[i],to[i]);
}
}
}
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(d[top[x]]>d[top[y]])
{
swap(x,y);
}
y=f[top[y]];
}
return d[x]<d[y]?x:y;
}
void updata(int &rt,int l,int r,int k,int v)
{
if(!rt)
{
rt=++cnt;
}
sum[rt]+=v;
if(l==r)
{
return ;
}
int mid=(l+r)>>1;
if(k<=mid)
{
updata(ls[rt],l,mid,k,v);
}
else
{
updata(rs[rt],mid+1,r,k,v);
}
}
int query(int l,int r,int k)
{
if(l==r)
{
return l;
}
int res=0;
for(int i=1;i<=s1[0];i++)
{
res+=sum[ls[s1[i]]];
}
for(int i=1;i<=s2[0];i++)
{
res+=sum[ls[s2[i]]];
}
for(int i=1;i<=s3[0];i++)
{
res-=sum[ls[s3[i]]];
}
for(int i=1;i<=s4[0];i++)
{
res-=sum[ls[s4[i]]];
}
int mid=(l+r)>>1;
if(k<=res)
{
for(int i=1;i<=s1[0];i++)
{
s1[i]=ls[s1[i]];
}
for(int i=1;i<=s2[0];i++)
{
s2[i]=ls[s2[i]];
}
for(int i=1;i<=s3[0];i++)
{
s3[i]=ls[s3[i]];
}
for(int i=1;i<=s4[0];i++)
{
s4[i]=ls[s4[i]];
}
return query(l,mid,k);
}
else
{
for(int i=1;i<=s1[0];i++)
{
s1[i]=rs[s1[i]];
}
for(int i=1;i<=s2[0];i++)
{
s2[i]=rs[s2[i]];
}
for(int i=1;i<=s3[0];i++)
{
s3[i]=rs[s3[i]];
}
for(int i=1;i<=s4[0];i++)
{
s4[i]=rs[s4[i]];
}
return query(mid+1,r,k-res);
}
}
void add(int k,int x,int v)
{
for(int i=x;i<=n;i+=i&(-i))
{
updata(root[i],0,100000000,k,v);
}
}
void ask(int x,int y,int k)
{
s1[0]=0;
s2[0]=0;
s3[0]=0;
s4[0]=0;
int anc=lca(x,y);
for(int i=s[x];i;i-=i&(-i))
{
s1[++s1[0]]=root[i];
}
for(int i=s[y];i;i-=i&(-i))
{
s2[++s2[0]]=root[i];
}
for(int i=s[anc];i;i-=i&(-i))
{
s3[++s3[0]]=root[i];
}
if(f[anc])
{
for(int i=s[f[anc]];i;i-=i&(-i))
{
s4[++s4[0]]=root[i];
}
}
int len=d[x]+d[y]-d[anc]-d[f[anc]];
if(len<k)
{
printf("invalid request!\n");
}
else
{
printf("%d\n",query(0,100000000,len-k+1));
}
}
void dfs(int x,int fa)
{
d[x]=d[fa]+1;
f[x]=fa;
size[x]=1;
s[x]=++num;
add(a[x],s[x],1);
for(int i=head[x];i;i=next[i])
{
if(to[i]!=fa)
{
dfs(to[i],x);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
{
son[x]=to[i];
}
}
}
t[x]=num+1;
add(a[x],t[x],-1);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
addd(x,y);
addd(y,x);
}
dfs(1,0);
dfs2(1,1);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&opt,&x,&y);
if(!opt)
{
add(a[x],s[x],-1);
add(a[x],t[x],1);
a[x]=y;
add(a[x],s[x],1);
add(a[x],t[x],-1);
}
else
{
ask(x,y,opt);
}
}
}

BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树的更多相关文章

  1. Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)

    E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...

  2. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  3. 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)

    题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路: ...

  4. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  5. CoderForces 163E e-Government(AC自动机+树状数组维护fail树的dfs序)

    E. e-Government time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  6. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

  7. [BZOJ 1146] [CTSC2008]网络管理Network(树状数组+主席树)

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  8. 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  9. POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

    Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 D ...

随机推荐

  1. SerialPort.h SerialPort.cpp

    SerialPort.h 1 #ifndef __SERIALPORT_H__ 2 #define __SERIALPORT_H__ 3 4 #define WM_COMM_BREAK_DETECTE ...

  2. (6)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- AOP框架

    AOP 框架基础 要求懂的知识:AOP.Filter.反射(Attribute). 如果直接使用 Polly,那么就会造成业务代码中混杂大量的业务无关代码.我们使用 AOP (如果不了解 AOP,请自 ...

  3. Mvc4_ @RenderBody、@RenderPage、@RenderSection用法

    一.@RenderBody 当创建基于_Layout.cshtml布局页面的视图时,视图的内容会和布局页面合并,而新创建视图的内容会通过_Layout.cshtml布局页面的@RenderBody() ...

  4. ARM-GPIO

    操作GPIO有三种方法: 调用库函数读取IO的输入电平:uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx,uint16_t GPIO_pin): 操作寄 ...

  5. BAT大厂面试流程剖析

    在当今互联网中,虽然互联网行业从业者众多,不断崛起的互联网公司也会很多,但如BAT等大厂,仍然是很多同学想要进入的企业.那么本篇文章将会为大家很直白的讲解大厂的面试流程以及侧重点. 首先闲聊一下,为什 ...

  6. 个人博客作业Week3--必应词典案例分析

    第一部分  调研,评测 (软件的bug,功能评测,黑箱测试,第8章 用户调研,12 章软件的用户体验) 下载并使用,按照描述的bug定义,找出几个功能性的比较严重的bug.至少两个.用专业的语言描述( ...

  7. 个人作业Week1

    一.<构建之法>提问 1.需求是什么?需求的规范需要明确吗? 2.一个人开发效率非常高,多人开发,个人效率随团队人数上升而直线下降,我们一般需要将大项目拆为小项目,使协作耦合产生的效率负影 ...

  8. Redis学习笔记之多机数据库

    1.复制 完整重同步,从服务器完全复制主服务器的数据,主要通过RDB文件和单条命令传输(套接字连接). 部分重同步,主服务器进行命令传播的时候,不仅会把写命令发送给从服务器,而且还会把写命令放入复制积 ...

  9. Linux 第七周实验 及总结

    姬梦馨 原创作品 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 第七周 Linux内核如何装载和启动一 ...

  10. 20135316Linux内核学习笔记第六周

    20135316王剑桥<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC 1000029000 一.进程控制块PCB--task_ ...