题面

题解

为了一点小细节卡了一个下午……我都怕我瞎用set把电脑搞炸……

观察一次\(1\)操作会造成什么影响,比如说把\(A[i]\)从\(x\)改成\(y\):

\(D[x]\)会\(-1\),导致\(E[x]=B[x]/D[x]\)会修改

\(D[y]\)会\(+1\),导致\(E[y]=B[y]/D[y]\)会修改

连边关系会修改

当某个\(E[x]\)改变时,所有跟它距离不超过\(1\)的点的\(C[]\)值都要修改

\(C[A[x]]\):单点修改

\(C[x]\):单点修改

儿子们的\(C[]\):打个标记

那么思路就明确了:对每个点搞个\(set\)维护它的儿子

修改单点的时候从父亲的\(set\)里拿出来,修改掉再插回去

对儿子整体修改的时候打标记

在全局再开两个\(set\),分别维护所有\(set\)最小值的最小值、最大值的最大值

断开/连接一条边的时候把标记的贡献算一下

以上是官方题解,这里说几个细节:

因为对于儿子们的\(C_i\),是所有的儿子和父亲的\(E_i\)之和加上一堆乱七八糟的东西,所以算儿子的\(C_i\)时可以不加上父亲的\(E_i\),等需要答案的时候再加上去,这样修改的时候可以直接更新父亲的\(E_i\)即可

最后,注意细节

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define IT multiset<ll>::iterator
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
ll read(){
R ll res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R ll x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5;
ll b[N],c[N],e[N];int to[N],d[N],n,m,op,x,y;
multiset<ll>s[N],mn,mx;IT it;
void update(int x,ll vva,ll val,int ty){
if(!s[x].empty()){
it=mn.lower_bound((*s[x].begin())+e[x]),mn.erase(it);
it=mx.lower_bound((*--s[x].end())+e[x]),mx.erase(it);
}
// printf("%d\n",m);
if(ty==-1)it=s[x].lower_bound(vva),s[x].erase(it);
it=mn.lower_bound((*s[to[x]].begin())+e[to[x]]),mn.erase(it);
it=mx.lower_bound((*--s[to[x]].end())+e[to[x]]),mx.erase(it);
it=mn.lower_bound((*s[to[to[x]]].begin())+e[to[to[x]]]),mn.erase(it);
it=mx.lower_bound((*--s[to[to[x]]].end())+e[to[to[x]]]),mx.erase(it); it=s[to[x]].lower_bound(c[x]),s[to[x]].erase(it);
it=s[to[to[x]]].lower_bound(c[to[x]]),s[to[to[x]]].erase(it); c[to[x]]-=e[x],c[x]-=b[x]-d[x]*e[x]+e[x],d[x]+=ty;
e[x]=b[x]/d[x],c[x]+=b[x]-d[x]*e[x]+e[x],c[x]+=ty*val,c[to[x]]+=e[x]; if(ty==1)s[x].insert(vva);
s[to[x]].insert(c[x]),s[to[to[x]]].insert(c[to[x]]);
mn.insert((*s[to[x]].begin())+e[to[x]]);
mx.insert((*--s[to[x]].end())+e[to[x]]);
mn.insert((*s[to[to[x]]].begin())+e[to[to[x]]]);
mx.insert((*--s[to[to[x]]].end())+e[to[to[x]]]); if(!s[x].empty()){
mn.insert((*s[x].begin())+e[x]);
mx.insert((*--s[x].end())+e[x]);
}
}
int main(){
// freopen("testdata.in","r",stdin);
// freopen("testdata.out","w",stdout);
freopen("forest.in","r",stdin);
freopen("forest.out","w",stdout);
n=read(),m=read();
fp(i,1,n)b[i]=read(),++d[i];
fp(i,1,n)to[i]=read(),++d[i],++d[to[i]];
fp(i,1,n)e[i]=b[i]/d[i],c[i]=b[i]-d[i]*e[i]+e[i];
fp(i,1,n)c[to[i]]+=e[i];
fp(i,1,n)s[to[i]].insert(c[i]);
fp(i,1,n)if(!s[i].empty()){
mn.insert((*s[i].begin())+e[i]);
mx.insert((*--s[i].end())+e[i]);
}
while(m--){
op=read();
switch(op){
case 1:{
x=read(),y=read();if(to[x]==y)continue;
update(to[x],c[x],e[x],-1);
to[x]=y;
update(to[x],c[x],e[x],1);
break;
}
case 2:x=read(),print(c[x]+e[to[x]]);break;
case 3:print(*mn.begin()),sr[C]=' ',print(*--mx.end());break;
}
}return Ot(),0;
}

jzoj5989. 【北大2019冬令营模拟2019.1.6】Forest (set)的更多相关文章

  1. jzoj5990. 【北大2019冬令营模拟2019.1.6】Bear (状压dp)

    题面 题解 我永远讨厌dp.jpg 搞了一个下午优化复杂度最后发现只要有一个小trick就可以A了→_→.全场都插头dp就我一个状压跑得贼慢-- 不难发现我们可以状压,对于每一行,用状态\(S\)表示 ...

  2. jzoj5991. 【北大2019冬令营模拟2019.1.6】Juice

    题面 题解 好迷-- //minamoto #include<bits/stdc++.h> #define R register #define ll long long #define ...

  3. jzoj5984. 【北大2019冬令营模拟2019.1.1】仙人掌 (分块)

    题面 题解 数据结构做傻了.jpg 考虑每一个节点,它的儿子的取值最多只有\(O(\sqrt {m})\)种,那么可以用一个双向链表维护儿子的所有取值以及该取值的个数,那么对儿子节点修改一个值就是\( ...

  4. jzoj5983. 【北大2019冬令营模拟2019.1.1】多边形 (组合数学)

    这其实是道打表题--你看我代码就知道了-- 咳咳来点严谨证明好了-- 前方高能请注意 首先,正多边形近似于圆,可以看做在圆里内接多边形.圆内接多边形最多只有三个锐角.因为凸多边形的外角和为\(360\ ...

  5. JZOJ[5971]【北大2019冬令营模拟12.1】 party(1s,256MB)

    题目 题目大意 给你一棵树,在树上的某一些节点上面有人,要用最小的步数和,使得这些人靠在一起.所谓靠在一起,即是任意两个人之间的路径上没有空的节点(也就是连在一起). N≤200N \leq 200N ...

  6. [JZOJ5977] 【清华2019冬令营模拟12.15】堆

    题目 其中n,q≤500000n,q\leq 500000n,q≤500000 题目大意 让你维护一个堆.支持一下操作: 在某个点的下面加上另一个点,然后进行上浮操作. 询问某一点的权值. 思考历程 ...

  7. Visual Studio 2019 发布活动 - 2019 年 4 月 2 日

    Visual Studio 2019 发布活动 2019 年 4 月 2 日,星期二 | 上午 9:00 (PT) 围观: https://visualstudio.microsoft.com/zh- ...

  8. [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania

    [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...

  9. jzoj6101. 【GDOI2019模拟2019.4.2】Path

    题目链接:https://jzoj.net/senior/#main/show/6101 记\(f_i\)为从\(i\)号点走到\(n\)号点所花天数的期望 那么根据\(m\)条边等可能的出现一条和一 ...

随机推荐

  1. 【BZOJ4952】lydsy七月月赛 E 二分答案

    [BZOJ4952]lydsy七月月赛 E 题面 题解:傻题...二分答案即可,精度有坑. #include <cstdio> #include <cstring> #incl ...

  2. 九度OJ 1102:最小面积子矩阵 (DP、缓存、剪枝)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:1666 解决:504 题目描述: 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵(矩阵中元素个数为矩阵面积) 输入: ...

  3. TMS320C6478+MCP2515

    调一个驱动,将看过的资料记录下来. 这个驱动写得比较直观:http://www.51hei.com/bbs/dpj-114085-1.html

  4. Dockerfile指令:

    Dockerfile指令: 第一行注释,指令是大写字母开头, FROM指令: FROM<image>,后面跟镜像名, FROM<image>:<tag>,后面跟镜像 ...

  5. Bestcoder round 18---A题(素数筛+素数打表+找三个素数其和==n)

    Primes Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  6. CentOS 下源码安装LAMP环境

    一.简介 什么是LAMP    LAMP是一种Web网络应用和开发环境,是Linux, Apache, MySQL, Php/Perl的缩写,每一个字母代表了一个组件,每个组件就其本身而言都是在它所代 ...

  7. HDU5919 Sequence2

    传送门 这道题是主席树好题啊-- 题目大意:给定一个序列,每次给定一段区间,区间内所有不同的数第一次出现的位置排成一个序列,求这个序列的中位数. 其实求中位数并不是很难,只要我们能把这个序列中不同的数 ...

  8. windows切换到谷歌浏览器黑屏问题

    打开谷歌浏览器,找到右上角,点击设置,如下: 点击高级设置,如下: 关闭使用硬件加速模式,重新打开浏览器,即可.

  9. SIP呼叫流程典型流程图解及其详细解释

    目录(?)[+]   1.注册流程: 2.注销流程: 3. 基本呼叫建立过程: 4. 会话更改流程: 5. 正常呼叫释放过程: 6. 被叫忙呼叫释放: 7.被叫无应答流程一: 8.被叫无应答流程二: ...

  10. dubbo框架介绍

    1.背景 (#) 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当网站流量很小 ...