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

题解:

树套树.

之前做过不带修改的,感觉还挺容易的.

这次是带修改版本,就不能直接在树上建主席树了.

不同的是,我们对 $DFS$ 序建立主席树

考虑到每一次修改一个点,只会对该点的子树到根的路径产生影响.

在 DFS 序中,每个点的子树是一段连续的区间,直接用带修改主席树修改一波即可.

在 DFS 序中,每个点到根节点的路径和就是该点在 DFS 序中的前缀和.

这样进行修改和查询即可.

Code:

#include<bits/stdc++.h>
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
#define maxn 200000
#define N 180000
using namespace std;
int n,q, edges,cc,num;
//权值线段树
namespace Seg
{
#define mid ((l+r)>>1)
int rt[maxn],node[10][maxn],cnt[10];
int tot;
struct Node
{
int l,r,w;
}t[maxn*50];
void insert(int &x,int l,int r,int k,int delta)
{
if(!x) x=++tot;
t[x].w+=delta;
if(l==r) return;
if(k<=mid)
insert(t[x].l,l,mid,k,delta);
else
insert(t[x].r,mid+1,r,k,delta);
}
int lowbit(int t)
{
return t & (-t);
}
void update(int pos,int val,int delta)
{
while(pos<=N) insert(rt[pos],1,N,val,delta),pos+=lowbit(pos);
}
int query(int l,int r,int kth)
{
if(l==r) return l;
int sum=0;
for(int i=1;i<=cnt[0];++i) sum+=t[t[node[0][i]].r].w;
for(int i=1;i<=cnt[1];++i) sum+=t[t[node[1][i]].r].w;
for(int i=1;i<=cnt[2];++i) sum-=t[t[node[2][i]].r].w;
for(int i=1;i<=cnt[3];++i) sum-=t[t[node[3][i]].r].w;
if(sum < kth)
{
for(int i=1;i<=cnt[0];++i) node[0][i] = t[node[0][i]].l;
for(int i=1;i<=cnt[1];++i) node[1][i] = t[node[1][i]].l;
for(int i=1;i<=cnt[2];++i) node[2][i] = t[node[2][i]].l;
for(int i=1;i<=cnt[3];++i) node[3][i] = t[node[3][i]].l;
return query(l,mid,kth-sum);
}
else
{
for(int i=1;i<=cnt[0];++i) node[0][i] = t[node[0][i]].r;
for(int i=1;i<=cnt[1];++i) node[1][i] = t[node[1][i]].r;
for(int i=1;i<=cnt[2];++i) node[2][i] = t[node[2][i]].r;
for(int i=1;i<=cnt[3];++i) node[3][i] = t[node[3][i]].r;
return query(mid+1,r,kth);
}
}
// 关键字 : 位置
int Query(int a,int b,int c,int d,int kth)
{
cnt[0]=cnt[1]=cnt[2]=cnt[3]=0;
for(int i=a;i>0;i-=lowbit(i)) node[0][++cnt[0]] = rt[i];
for(int i=b;i>0;i-=lowbit(i)) node[1][++cnt[1]] = rt[i];
for(int i=c;i>0;i-=lowbit(i)) node[2][++cnt[2]] = rt[i];
for(int i=d;i>0;i-=lowbit(i)) node[3][++cnt[3]] = rt[i];
return query(1,N,kth);
}
};
struct Query
{
int opt,a,b;
}Q[maxn];
int hd[maxn],to[maxn],nex[maxn],dfs[maxn],arr[maxn],A[maxn];
int st[maxn],ed[maxn],F[20][maxn],dep[maxn],val[maxn];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
//read and diskreat
void read()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i) scanf("%d",&val[i]),A[++cc]=val[i];
for(int i=1,a,b;i<n;++i)
scanf("%d%d",&a,&b), add(a,b),add(b,a);
for(int i=1;i<=q;++i)
{
scanf("%d%d%d",&Q[i].opt,&Q[i].a,&Q[i].b);
if(Q[i].opt==0) A[++cc]=Q[i].b;
}
sort(A+1,A+1+cc);
for(int i=1;i<=q;++i) if(Q[i].opt==0) Q[i].b=lower_bound(A+1,A+1+cc,Q[i].b)-A;
for(int i=1;i<=n;++i) val[i] = lower_bound(A+1,A+1+cc,val[i])-A;
}
//求dfs序
void DFS(int u,int fa)
{
F[0][u]=fa, dep[u] = dep[fa] + 1;
for(int i=1;i<20;++i) F[i][u]=F[i-1][F[i-1][u]];
dfs[++num]=val[u],st[u]=num;
for(int i=hd[u];i;i=nex[i])
{
if(to[i]==fa) continue;
DFS(to[i],u);
}
ed[u]=num+1;
}
int LCA(int a,int b)
{
if(dep[b]<dep[a]) swap(a,b);
if(dep[a]!=dep[b])
{
for(int i=19;i>=0;--i) if(dep[F[i][b]] >= dep[a]) b = F[i][b];
}
if(a==b) return a;
for(int i=19;i>=0;--i)
{
if(F[i][a]!=F[i][b]) a = F[i][a], b = F[i][b];
}
return F[0][a];
}
int main()
{
// setIO("input");
read();
DFS(1,0);
for(int i = 1;i <= n; ++i)
{
Seg::update(st[i],val[i], 1);
Seg::update(ed[i],val[i], -1);
}
for(int i=1,a,b;i<=q;++i)
{
a = Q[i].a, b = Q[i].b;
if(Q[i].opt==0)
{
Seg::update(st[a], val[a], -1);
Seg::update(ed[a], val[a], 1);
val[a] = b;
Seg::update(st[a],val[a], 1);
Seg::update(ed[a],val[a], -1);
}
if(Q[i].opt>0)
{
int lca = LCA(a,b);
int c = Seg::Query(st[a],st[b],st[lca],st[F[0][lca]],Q[i].opt);
if(c==1)
printf("invalid request!\n");
else
printf("%d\n",A[c]);
}
}
return 0;
}

  

BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序的更多相关文章

  1. BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 3522  Solved: 1041[Submi ...

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

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

  3. BZOJ 1146: [CTSC2008]网络管理Network 树链剖分+线段树+平衡树

    1146: [CTSC2008]网络管理Network Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 870  Solved: 299[Submit] ...

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

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

  5. bzoj 1146 [CTSC2008]网络管理Network

    很久之前写过 count on the tree. 然后一直不懂树状数组是怎么套上这个主席树的. 看了两小时发现它套的就是个权值线段树, 看不出来可持久化在哪里. 因为动态开点所以空间nlog2n. ...

  6. BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树

    题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...

  7. 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理

    令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...

  8. 【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1146 第一种做法(时间太感人): 第二种做法(rank5,好开心) ================ ...

  9. 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树

    [BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...

随机推荐

  1. LinkedList,ArrayList末尾插入谁效率高?

    废话不多说,原因不解释.上測试代码: package com.letv.cloud.cdn.jtest; import java.io.IOException; import java.util.Ar ...

  2. poj 2931 Building a Space Station &lt;克鲁斯卡尔&gt;

    Building a Space Station Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 5869 Accepted: 2 ...

  3. Apache + Tomcat + JK 集群

    原文请见http://www.cnblogs.com/dennisit/p/3370220.html 本文介绍了集群和负载均衡的基本开源实现,实现了用Apache分发请求到多个Tomcat里面相应的应 ...

  4. iOS UITableView 去除多余切割线

    在UITableView初始化时加上下面代码就可以: self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero ...

  5. &quot;Hello World &quot; —— 深入理解程序从编译到执行

    对于C语言编写的Hello World程序(例如以下).对于程序猿来说肯定如雷贯耳,就是这样一个简单的程序,你真的了解她吗? #include <stdio.h> int main() { ...

  6. nyoj860 又见01背包(背包变形)

    题目860 pid=860" style="text-decoration:none; color:rgb(55,119,188)">题目信息 执行结果 本题排行 ...

  7. HDU 3656 二分+dlx判定

    Fire station Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  8. ExtJs 给grid某一单元格重新赋值

    // 司机,搬运工提成 var commissionMoney = (waybillsFtQty * commissionMoneyRatio / personCount).toFixed(2); / ...

  9. K度限制MST poj 1639

    /* k度限制MST:有一个点的度<=k的MST poj 1639 要求1号点的度不超过k 求MST 我们先把1号点扔掉 跑MST 假设有sum个连通分支 然后把这sum个分支连到1上 就得到了 ...

  10. 如何更改iTunes备份地址(修改iphone ipad 备份地址) itunes文件目录修改方法 【亲测有效,附带原理说明】

    前言 C盘空间有限,但是iTunes就是那么龌龊,只能把手机备份存到C盘.那么怎么才能把备份文件存到其他分区的文件夹里面呢? 当时我想先看看度娘,看看有没有现成的! 结果 nnd!! 我看了一大堆相关 ...