1146: [CTSC2008]网络管理Network

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!”(全部小写不包含引号,两个单词之间有一个空格)。

蒟弱写的第一篇blog,好兴奋!

思路:树链剖分+树套树。

首先树链剖分一下,接下来线段树套Treap,修改时就在线段树上走一下,删除原来的值并且插入新的值。查询时,二分答案,求mid的排名,逐渐向答案逼近。查询排名,就是求比这个数小的数的个数+1。为了效率不至于太低,我离散化了一下。细节详见代码。时间复杂度线段树一个log,Treap还有一个log,查询还有树剖1个log,二分1个log。因此修改是2个log,查询是4个log,总时间复杂度O(nlog^4n)。 码得好爽啊,260行代码居然没有调试,1A。但是。。。。。。这份代码跑得像shi一样慢,30s+。废话4个log能跑多快。

代码:

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline int rd()
{char ch=getchar();int ret=0,f=1;while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}return ret*f;
}
const int N=80005;
int n,q,u,v,cnt=0,idx=0,tot=0,ans,a[N],hash[N*2],K[N],A[N],B[N],root[N*4];
int head[N],to[N*2],nxt[N*2],size[N],son[N],dep[N],fa[N],pos[N],top[N];
int mempool[N*20],key[N*20],rnd[N*20],siz[N*20],w[N*20],ch[N*20][2];
int ins,rmv;
int getid(int x)
{return lower_bound(hash+1,hash+hash[0]+1,x)-hash;
}
void adde(int u,int v)
{to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
}
void dfs1(int u)
{size[u]=1;for(int v=head[u];v;v=nxt[v])if(to[v]!=fa[u]){fa[to[v]]=u;dep[to[v]]=dep[u]+1;dfs1(to[v]);size[u]+=size[to[v]];if(!son[u]||size[son[u]]<size[to[v]])son[u]=to[v];}
}
void dfs2(int u,int tp)
{pos[u]=++idx;top[u]=tp;if(son[u]) dfs2(son[u],tp);for(int v=head[u];v;v=nxt[v])if(to[v]!=fa[u]&&to[v]!=son[u])dfs2(to[v],to[v]);
}
void maintain(int k)
{siz[k]=siz[ch[k][0]]+siz[ch[k][1]]+w[k];
}
void rturn(int &k)
{int t=ch[k][0];ch[k][0]=ch[t][1];ch[t][1]=k;siz[t]=siz[k];maintain(k);k=t;
}
void lturn(int &k)
{int t=ch[k][1];ch[k][1]=ch[t][0];ch[t][0]=k;siz[t]=siz[k];maintain(k);k=t;
}
void insert(int &k,int x)
{if(!k){k=mempool[mempool[0]--];key[k]=x;rnd[k]=rand();siz[k]=w[k]=1;ch[k][0]=ch[k][1]=0;return;}siz[k]++;if(x==key[k]) w[k]++;else if(x<key[k]){insert(ch[k][0],x);if(rnd[ch[k][0]]<rnd[k]) rturn(k);}else{insert(ch[k][1],x);if(rnd[ch[k][1]]<rnd[k]) lturn(k);}
}
void remove(int &k,int x)
{if(x==key[k]){if(w[k]>1){siz[k]--;w[k]--;return;}else if(ch[k][0]*ch[k][1]==0){mempool[++mempool[0]]=k;if(!ch[k][0]) k=ch[k][1];else k=ch[k][0];}else{if(rnd[ch[k][0]]>rnd[ch[k][1]]) lturn(k);else rturn(k);remove(k,x);}}else{siz[k]--;if(x<key[k]) remove(ch[k][0],x);else remove(ch[k][1],x);}
}
void rnk(int k,int x)
{while(k){if(x<=key[k]) k=ch[k][0];else{ans+=siz[ch[k][0]]+w[k];k=ch[k][1];}}
}
void build(int o,int l,int r,int k)
{insert(root[o],ins);if(l==r) return;int mid=(l+r)/2;if(k<=mid) build(o*2,l,mid,k);else build(o*2+1,mid+1,r,k);
}
void change(int o,int l,int r,int k)
{remove(root[o],rmv);insert(root[o],ins);if(l==r) return;int mid=(l+r)/2;if(k<=mid) change(o*2,l,mid,k);else change(o*2+1,mid+1,r,k);
}
void query(int o,int l,int r,int L,int R,int k)
{if(L<=l&&R>=r){rnk(root[o],k);return;}int mid=(l+r)/2;if(L<=mid) query(o*2,l,mid,L,R,k);if(R>mid) query(o*2+1,mid+1,r,L,R,k);
}
int LCA(int u,int v)
{while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);u=fa[top[u]];}if(dep[u]>dep[v]) swap(u,v);return u;
}
void solvequery(int u,int v,int k)
{while(top[u]!=top[v]){if(dep[top[u]]<dep[top[v]]) swap(u,v);query(1,1,n,pos[top[u]],pos[u],k);u=fa[top[u]];}if(dep[u]>dep[v]) swap(u,v);query(1,1,n,pos[u],pos[v],k);
}
int main()
{for(int i=1600000;i>=1;i--) mempool[++mempool[0]]=i;n=rd(),q=rd();for(int i=1;i<=n;i++)hash[++hash[0]]=a[i]=rd();for(int i=1;i<n;i++){scanf("%d%d",&u,&v);adde(u,v);adde(v,u);}dfs1(1);dfs2(1,1);for(int i=1;i<=q;i++){K[i]=rd(),A[i]=rd(),B[i]=rd();if(!K[i]) hash[++hash[0]]=B[i];}sort(hash+1,hash+hash[0]+1);hash[0]=unique(hash+1,hash+hash[0]+1)-hash-1;for(int i=1;i<=n;i++){ins=getid(a[i]);build(1,1,n,pos[i]);}for(int i=1;i<=q;i++){if(!K[i]){ins=getid(B[i]);rmv=getid(a[A[i]]);change(1,1,n,pos[A[i]]);a[A[i]]=B[i];}else{int lca=LCA(A[i],B[i]),siz=dep[A[i]]+dep[B[i]]-dep[lca]*2+1;if(siz<K[i]){puts("invalid request!");continue;}K[i]=siz-K[i]+1;int l=1,r=hash[0],tmp;while(l<=r){int mid=(l+r)/2;ans=1;solvequery(A[i],B[i],mid);if(ans<=K[i]){l=mid+1;tmp=mid;}else r=mid-1;}printf("%d\n",hash[tmp]);}}return 0;
}


转载于:https://www.cnblogs.com/2016gdgzoi471/p/9476919.html

【bzoj1146】 [CTSC2008]网络管理Network【树链剖分+树套树+二分 线段树套Treap】相关推荐

  1. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  2. 树链剖分 or 根号分治 + dfs序 + 树状数组 ---- CF1254 D. Tree Queries

    题目链接 题目大意: 问题转化: 很容易发现:假设修改的节点是vvv. 1.vvv的子树sonvson_vsonv​直接加上(n−size[sonv])n×d\frac{(n-size[son_v]) ...

  3. 树剖+线段树||树链剖分||BZOJ1984||Luogu4315||月下“毛景树”

    题面:月下"毛景树" 题解:是道很裸的树剖,但处理的细节有点多(其实是自己线段树没学好).用一个Dfs把边权下移到点权,用E数组记录哪些边被用到了:前三个更新的操作都可以合并起来, ...

  4. BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...

  5. SPOJ - QTREE3Query on a tree again!——树链剖分

    [题目描述] SPOJ - QTREE3Query on a tree again! [题目分析] 题目要求是输出从111到xxx的路径上遇到的第一个黑色的点.我们可以用树链剖分(不了解的同学请出门左 ...

  6. bzoj 3626: [LNOI2014]LCA(离线差分+树链剖分)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2885  Solved: 1133 [Submit][Sta ...

  7. HDU 3966 POJ 3237 HYSBZ 2243 HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  8. E. Tree(The 2019 ACM-ICPC China Shannxi Provincial Programming Contest)(树链剖分+线段树)

    4000ms 262144K judge:计蒜客 Description Ming and Hong are playing a simple game called nim game. They h ...

  9. 树链剖分(轻重链)入门

    写在前面 仅想学树剖LCA的同学其实不必要了解线段树 前置知识:树形结构,链式前向星(熟练),线段树(熟练),DFS序(熟练),LCA(了解定义) 树链剖分(树剖):将树分解为一条条不相交的,从祖先到 ...

最新文章

  1. stm32编码器正反转计数程序_编码器接线方法你会吗?
  2. War包与配置文件分离
  3. E2. 比昨天更多的棒棒糖 (Hard)
  4. go reflect 取指针_Go的方法集详解
  5. mybatis-通用Mapper
  6. 使用 systemd 定时器调度任务
  7. 1.数据结构 --- 绪论
  8. opencv-python版本问题
  9. 网站html导出excel插件,使用JQuery插件将HTML的table标签数据导出成excel
  10. 优启通制作系统u盘_优启通 v3.6.2020.0620 VIP版/免费版-好用的U盘启动盘制作工具...
  11. 程序员的超强本地构建工具
  12. SLAM之PTAM学习笔记
  13. 最小二乘法曲线拟合(代码环境:matlab)
  14. Aptana 安装与配置
  15. C++幕后故事(七)--一个对象的生与死
  16. 2022-2027年中国微创介入医疗器械市场竞争态势及行业投资前景预测报告
  17. MP4视频太大怎么在线压缩
  18. 讯飞实时语音转写 python3.6.1 可完美运行 解析返回的json字符串 输出所获语音文字
  19. 主板和机箱螺丝孔对不上?
  20. zuk z2 android 7.0,联想ZUK Z2兑现承诺,即将推出安卓7.0更新

热门文章

  1. Mysql经常使用函数汇总
  2. 《众妙之门——用户体验设计的秘密》一2.3 触摸至上的设计
  3. Linux下testlink安装
  4. Ubuntu安装Chrome的方法
  5. 虚拟机ping不通主机与外网的解决方法
  6. linux中date命令设置系统时间的方法-转
  7. C语言 n的作业,C语言作业练习
  8. java子字符串查找位置_初学者求教,如何在字符串中查找多个子字符串的位置...
  9. 蓝桥杯 ADV-162 算法提高 题目1 最大最小值
  10. 【操作系统】用户可通过三种方式使用计算机