洛谷P4175 - [CTSC2008]网络管理
Description
给出一棵\(n(n\leq8\times10^4)\)个点的带点权的树,进行\(m(m\leq8\times10^4)\)次操作,操作有两种:
- 修改一个点的点权。
- 询问路径\((u,v)\)上第\(k\)大的点权。若路径上的点不足\(k\)个输出
invalid request!。
Solution
带修改的可持久化线段树。
首先对于每个节点\(u\)建立一棵线段树记录路径\((u,rt)\)上的权值分布。考虑修改一个点的权值对这些线段树有什么影响。当\(u\)的权值由\(val\)变为\(val'\)后,子树\(u\)中的所有点的线段树中都有\(cnt[val]-1,cnt[val']+1\)。
对每个点再建立一棵线段树记录修改。修改子树在DFS序上相当于修改区间,差分后变为两个单点修改。于是我们要对于这些线段树进行单点修改,前缀查询;而这可以用树状数组实现。于是我们按DFS序建立树状数组套线段树就可以维护修改带来的影响。当我们需要求路径\((u,rt)\)上的权值分布时,用原线段树加上修改线段树即可。
时间复杂度\(O(mlog^3n)\)。
Code
//[CTSC2008]网络管理
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
inline char gc()
{
static char now[1<<16],*s,*t;
if(s==t) {t=(s=now)+fread(now,1,1<<16,stdin); if(s==t) return EOF;}
return *s++;
}
inline int read()
{
int x=0; char ch=gc();
while(ch<'0'||'9'<ch) ch=gc();
while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
return x;
}
const int N=8e4+10;
int n,m,w[N];
struct optR{int k,u,v;} seq[N];
int wCnt,map[N<<1];
void discrete()
{
int cnt=0;
for(int i=1;i<=n;i++) map[++cnt]=w[i];
for(int i=1;i<=m;i++) if(seq[i].k==0) map[++cnt]=seq[i].v;
sort(map+1,map+cnt+1); wCnt=unique(map+1,map+cnt+1)-map-1;
for(int i=1;i<=n;i++) w[i]=lower_bound(map+1,map+wCnt+1,w[i])-map;
for(int i=1;i<=m;i++) if(seq[i].k==0) seq[i].v=lower_bound(map+1,map+wCnt+1,seq[i].v)-map;
}
const int N1=2e7;
int ndCnt,rt1[N],rt2[N],ch[N1][2],sum[N1];
void trAdd(int t,int x,int v);
int trSum(int t,int L,int R);
void ndCopy(int p,int q) {ch[q][0]=ch[p][0],ch[q][1]=ch[p][1],sum[q]=sum[p];}
void ins1(int &p,int L0,int R0,int x)
{
ndCopy(p,++ndCnt); sum[p=ndCnt]++;
if(L0==R0) return;
int mid=L0+R0>>1;
if(x<=mid) ins1(ch[p][0],L0,mid,x);
else ins1(ch[p][1],mid+1,R0,x);
}
int t1,t2,t3,t4;
int query1(int p1,int p2,int p3,int p4,int L0,int R0,int k)
{
if(L0==R0) return map[L0];
int mid=L0+R0>>1,sumL=0;
sumL+=sum[ch[p1][0]]+trSum(t1,L0,mid)+sum[ch[p2][0]]+trSum(t2,L0,mid);
sumL-=sum[ch[p3][0]]+trSum(t3,L0,mid)+sum[ch[p4][0]]+trSum(t4,L0,mid);
if(sumL>=k) return query1(ch[p1][0],ch[p2][0],ch[p3][0],ch[p4][0],L0,mid,k);
else return query1(ch[p1][1],ch[p2][1],ch[p3][1],ch[p4][1],mid+1,R0,k-sumL);
}
void ins2(int &p,int L0,int R0,int x,int v)
{
if(!p) p=++ndCnt; sum[p]+=v;
if(L0==R0) return;
int mid=L0+R0>>1;
if(x<=mid) ins2(ch[p][0],L0,mid,x,v);
else ins2(ch[p][1],mid+1,R0,x,v);
}
int query2(int p,int L0,int R0,int optL,int optR)
{
if(optL<=L0&&R0<=optR) return sum[p];
int mid=L0+R0>>1,r=0;
if(optL<=mid) r+=query2(ch[p][0],L0,mid,optL,optR);
if(mid<optR) r+=query2(ch[p][1],mid+1,R0,optL,optR);
return r;
}
void trAdd(int t,int x,int v) {while(t<=n) ins2(rt2[t],1,wCnt,x,v),t+=t&(-t);}
int trSum(int t,int L,int R)
{
int r=0;
while(t) r+=query2(rt2[t],1,wCnt,L,R),t-=t&(-t);
return r;
}
vector<int> ed[N];
void edAdd(int u,int v) {ed[u].push_back(v),ed[v].push_back(u);}
int fa[N][20],dpt[N]; int dfCnt,fr[N],to[N];
void dfs(int u)
{
fr[u]=++dfCnt;
ins1(rt1[u]=rt1[fa[u][0]],1,wCnt,w[u]);
for(int k=1;fa[u][k-1];k++) fa[u][k]=fa[fa[u][k-1]][k-1];
for(int i=0;i<ed[u].size();i++)
{
int v=ed[u][i];
if(v==fa[u][0]) continue;
fa[v][0]=u,dpt[v]=dpt[u]+1;
dfs(v);
}
to[u]=dfCnt;
}
int lca(int u,int v)
{
if(dpt[u]<dpt[v]) swap(u,v);
for(int k=17;k>=0;k--) if(dpt[fa[u][k]]>=dpt[v]) u=fa[u][k];
if(u==v) return u;
for(int k=17;k>=0;k--) if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k];
return fa[u][0];
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++) w[i]=read();
for(int i=1;i<=n-1;i++) edAdd(read(),read());
for(int i=1;i<=m;i++) seq[i].k=read(),seq[i].u=read(),seq[i].v=read();
discrete();
dpt[1]=1,dfs(1);
for(int i=1;i<=m;i++)
{
int k=seq[i].k,u=seq[i].u,v=seq[i].v;
if(k==0)
{
trAdd(fr[u],w[u],-1),trAdd(to[u]+1,w[u],1);
w[u]=v; trAdd(fr[u],v,1),trAdd(to[u]+1,v,-1);
}
else
{
int u1=lca(u,v),v1=fa[u1][0],sum1=0;
t1=fr[u],t2=fr[v],t3=fr[u1],t4=fr[v1];
sum1+=sum[rt1[u]]+trSum(t1,1,wCnt)+sum[rt1[v]]+trSum(t2,1,wCnt);
sum1-=sum[rt1[u1]]+trSum(t3,1,wCnt)+sum[rt1[v1]]+trSum(t4,1,wCnt);
if(sum1<k) puts("invalid request!");
else printf("%d\n",query1(rt1[u],rt1[v],rt1[u1],rt1[v1],1,wCnt,sum1-k+1));
}
}
return 0;
}
P.S.
姑且是把之前鸽了的题解都补完了...
洛谷P4175 - [CTSC2008]网络管理的更多相关文章
- 洛谷 P4175 [CTSC2008]网络管理 解题报告
P4175 [CTSC2008]网络管理 题目描述 带修改树上链的第\(k\)大 输入输出格式 输入格式: 第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数. 第二行有\(N\) ...
- 洛谷 P4175: bzoj 1146: [CTSC2008]网络管理
令人抓狂的整体二分题.根本原因还是我太菜了. 在学校写了一个下午写得头晕,回家里重写了一遍,一个小时就写完了--不过还是太慢. 题目传送门:洛谷P4175. 题意简述: 一棵 \(n\) 个结点的树, ...
- 洛谷P4175 网络管理
题意:链上带修第k大. 这毒瘤题...别看题意只有7个字,能把我吊打死... 介绍其中两种做法好了.其实思想上是一样的. 对于每一个点,建立权值线段树,维护它到根路径上的所有权值. 一条路径上的点集就 ...
- P4175 [CTSC2008]网络管理
如果没有修改就是简单主席树,有了修改的话因为主席树维护的是到根的一段路径,所以修改操作会修改子树,也就是连续的一段dfn 所以显然树套树一波就没了 极其好写 #include<bits/stdc ...
- P4175 [CTSC2008]网络管理 树剖+树套树
$ \color{#0066ff}{ 题目描述 }$ M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 ...
- 洛谷 P4298: bzoj 1143: [CTSC2008]祭祀
题目传送门:洛谷 P4298. 题意简述: 给定一个 \(n\) 个点,\(m\) 条边的简单有向无环图(DAG),求出它的最长反链,并构造方案. 最长反链:一张有向无环图的最长反链为一个集合 \(S ...
- 【LG4175】[CTSC2008]网络管理
[LG4175][CTSC2008]网络管理 题面 洛谷 题解 感觉就和普通的整体二分差不太多啊... 树上修改就按时间添加,用树状数组维护一下即可 代码 #include<iostream&g ...
- BZOJ 1146: [CTSC2008]网络管理Network [树上带修改主席树]
1146: [CTSC2008]网络管理Network Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 3522 Solved: 1041[Submi ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
随机推荐
- 解决sublime text 2总是在新窗口中打开文件(标签中打开)
在mac下不是很喜欢sublime text 2 总是在新窗口中打开文件,很麻烦,文件打多了,就会出现N多窗口,虽然可以直接打开当前目录可以解决,但有时候查看其它项目中的单个文件,就比较麻烦.百度一直 ...
- 【转载】Alpha、Beta、RC、GA版本的区别
转自:http://www.blogjava.net/RomulusW/archive/2008/05/04/197985.html Alpha:是内部测试版,一般不向外部发布,会有很多Bug.一般只 ...
- VMware vSphere6.0 服务器虚拟化部署安装图解
一 VMware vSphere部署的前期规划要点 1 vSphere的优点 (略) 2 如何利用现在的设备架构虚拟化环境 在虚拟化过程中,用户大多会考虑目前现有的服务器.存储.交换机等基础设备是否可 ...
- maven,gradle本地缓存位置
gradle: 配置系统环境变量GRADLE_USER_HOME即可,值为缓存位置. maven: 修改settings文件:maven的home路径下的conf文件夹下的settings.xml 对 ...
- cocos2dx通过ndk编译c++库
ndk编译c++库,然后通过jni调用实现重要代码封装,是安卓应用中最常用的技术,一方面可以将重要的代码实现隐藏,防止泄漏,也可以提高打包速度. ndk里面的sample文件夹中有很多实用的例子,其中 ...
- const 修饰成员函数 前后用法(effective c++ 03)
目录 const在函数后面 const修饰成员函数的两个作用 const在函数前面 总结 const在函数后面 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态 ...
- Codevs1080 线段树练习
题目描述 Description 一行N个方格,开始每个格子里都有一个整数.现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和:修改的规则是指定某一个格子x,加上或 ...
- Leetcode 20 有效的括号valid-parentheses(栈)
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. 注意空字符串可被认 ...
- Java常用的一些容器
转自:https://www.cnblogs.com/LipeiNet/p/5888513.html 前言:在java开发中我们肯定会大量的使用集合,在这里我将总结常见的集合类,每个集合类的优点和缺点 ...
- 【思维题 kmp 构造】bzoj4974: [Lydsy1708月赛]字符串大师
字符串思博题这一块还是有点薄弱啊. Description 一个串T是S的循环节,当且仅当存在正整数k,使得S是T^k(即T重复k次)的前缀,比如abcd是abcdabcdab的循环节 .给定一个长度 ...