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. UVA 11468 Substring (AC自动机)

    用把失配边也加到正常边以后AC自动机,状态是长度递减的DAG,每次选一个不会匹配字符的转移. dp[u][L]表示当前在tire树上u结点长度还剩L时候不匹配的概率,根据全概率公式跑记忆化搜索. #i ...

  2. Android(java)学习笔记135:SQLite数据库(表)的创建 以及 SQLite数据库的升级

    一.数据库的创建 1.文件的创建      //引用,如果文件不存在是不会创建的   File  file = new File("haha.txt"):     //输出流写数据 ...

  3. Typescript的优势

    TypeScript是一种由微软开发的自由开源的编程语言,他是JavaScript的一个超集,扩展了JavaScript的语法. 优势: 一.Angular2框架的开发语言 Angular2是一款开源 ...

  4. GCD 代码以及GCD思想

    # 欧几里得算法 现在,我们来学习一下欧几里得算法. 欧几里得算法又称辗转相除法,主要用于算求两个正数之间的最大公约数.对于最大公约数这个名称,其英文名称为(Greatest Common Divis ...

  5. python_98_面向对象_学校

    class School(object):#以后都加object(基类) def __init__(self, name, addr): self.name = name self.addr = ad ...

  6. Win10激活方法(企业版)

    Win10激活 注意:以管理员身份运行,需要电脑有网(亲测激活企业版没问题) 然后一条一条复制执行 slmgr /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43 slmgr /sk ...

  7. SC || 解决在git中上传过大文件的问题(如何将提交过的彻底删除

    就在我在ddl前续命的时候……不知道怎么想不开,把v2的压力测试的日志(500多M)也往github上传 之前听说过好多因为传了大文件的锅…… 我竟然还想不开的往上传…… 真实又傻又蠢又自闭(T T ...

  8. 数据库连接池 dbcp与c3p0的使用区别

    众所周知,无论现在是B/S或者是C/S应用中,都免不了要和数据库打交道.在与数据库交 互过程中,往往需要大量的连接.对于一个大型应用来说,往往需要应对数以千万级的用户连接请求,如果高效相应用户请求,对 ...

  9. Kenneth A.Lambert著的数据结构(用python语言描述)的第一章课后编程答案

    第6题:工资部门将每个支付周期的雇员信息的列表保存到一个文本文件, 每一行的格式:<last name><hourly wage><hours worked> 编写 ...

  10. vue之列表循环

    文档:https://cn.vuejs.org/v2/guide/list.html 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略.如果数据项的顺序被改变, ...