Portal

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]网络管理的更多相关文章

  1. 洛谷 P4175 [CTSC2008]网络管理 解题报告

    P4175 [CTSC2008]网络管理 题目描述 带修改树上链的第\(k\)大 输入输出格式 输入格式: 第一行为两个整数\(N\)和\(Q\),分别表示路由器总数和询问的总数. 第二行有\(N\) ...

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

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

  3. 洛谷P4175 网络管理

    题意:链上带修第k大. 这毒瘤题...别看题意只有7个字,能把我吊打死... 介绍其中两种做法好了.其实思想上是一样的. 对于每一个点,建立权值线段树,维护它到根路径上的所有权值. 一条路径上的点集就 ...

  4. P4175 [CTSC2008]网络管理

    如果没有修改就是简单主席树,有了修改的话因为主席树维护的是到根的一段路径,所以修改操作会修改子树,也就是连续的一段dfn 所以显然树套树一波就没了 极其好写 #include<bits/stdc ...

  5. P4175 [CTSC2008]网络管理 树剖+树套树

    $ \color{#0066ff}{ 题目描述 }$ M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通 ...

  6. 洛谷 P4298: bzoj 1143: [CTSC2008]祭祀

    题目传送门:洛谷 P4298. 题意简述: 给定一个 \(n\) 个点,\(m\) 条边的简单有向无环图(DAG),求出它的最长反链,并构造方案. 最长反链:一张有向无环图的最长反链为一个集合 \(S ...

  7. 【LG4175】[CTSC2008]网络管理

    [LG4175][CTSC2008]网络管理 题面 洛谷 题解 感觉就和普通的整体二分差不太多啊... 树上修改就按时间添加,用树状数组维护一下即可 代码 #include<iostream&g ...

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

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

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

随机推荐

  1. UVA11019 Matrix Matcher (AC自动机)

    二维的矩阵匹配,把模式矩阵按列拆开构造AC自动机,记录行号(为了缩点判断). 把T矩阵按行匹配,一旦匹配成功,在假想的子矩阵左上角位置加一.最后统计总数. 因为所有模式串长度一样,不用维护last数组 ...

  2. 个人对spring的IOC+DI的封装

    暂时支持8种基本数据类型,String类型,引用类型,List的注入. 核心代码 package day01; import java.lang.reflect.Field;import java.l ...

  3. Xcode 的expression命令

    expression命令是执行一个表达式,并将表达式返回的结果输出,是LLDB调试命令中最重要的命令,也是我们常用的 p 和 po 命令的 鼻祖. 他主要有2个功能 (1) 执行表达式 举例:改变视图 ...

  4. iOS--获取文件目录的方法

    很多文章都有写这个问题,我只是为了记录一下,免得总翻书... 1.Documents 目录: 你应该将所有的应用程序数据文件写入到这个目录下.这个目录用于存储用户数据或其它应该定期备份的信息. 2.L ...

  5. python列表之append与extend方法比较

    append和extend是列表的两种添加元素方式,但这两种方式却又有些不同之处.那么不同之处在哪里呢,我们通过对二者的定义和实例来看一看. list.append() 1.定义:L.append(o ...

  6. Ubuntu下删除mysql数据库

    Ubuntu下删除mysql数据库 sudo apt-get autoremove --purge mysql-server-5.7 sudo apt-get remove mysql-server ...

  7. Linux菜鸟起飞之路【九】系统启动流程

    Linux系统启动流程 BIOS -> MBR  -> BootLoader -> Kernel -> init 1.打开电源后,计算机从主板的BIOS中读取其中存储的程序.这 ...

  8. Tcl/Cmds

  9. 一个form表单对应多个submit

    一个form表单多个submit 在平时项目开发过程中,经常会遇到一个form表单对应多个submit提交的情况,那么 ,这种情况应该怎么解决呢,也很简单,这时候就不能用submit来提交了,可以通过 ...

  10. 【mac】【转发】Mac系统升级后,按大小写键没反应了,切换大小写的灯不亮了

    Mac系统升级后发现caps lock 锁定大小写的键,失灵了,居然可以用来切换输入法了,经过一排查后, 使用以下几种方法处理: 方式一:长按 caps lock 键,来切换大小写 方式二:caps ...