题面

题解

为了一点小细节卡了一个下午……我都怕我瞎用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. EasyPlayer实现视频播放局部缩放、广角平移功能(类似水滴直播,快手视频)

    本文转自:http://blog.csdn.net/jyt0551/article/details/56063869 视频播放局部缩放.广角平移功能 在预览图片的时候,利用手势控制图片的缩放.平移,已 ...

  2. [SCOI2009] 最长距离

    题目描述 windy有一块矩形土地,被分为 NM 块 11 的小格子. 有的格子含有障碍物. 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离. 如果从格子A不可以走到格子 ...

  3. iOS 工程中 Other Linker Flags

    对于64位机子和iPhone OS应用 解决方法是使用-all_load 或者 -force_load. -all_load强迫链接器从它能看见的所有文档中加载所有的对象文件,甚至那些没有OC代码的文 ...

  4. leetcode 750. Number Of Corner Rectangles

    Given a grid where each entry is only 0 or 1, find the number of corner rectangles. A corner rectang ...

  5. 理解vue ssr原理,自己搭建简单的ssr框架

    前言 大多数Vue项目要支持SSR应该是为了SEO考虑,毕竟对于WEB应用来说,搜索引擎是一个很大的流量入口.Vue SSR现在已经比较成熟了,但是如果是把一个SPA应用改造成SSR应用,成本还是有些 ...

  6. "未预编译文件 因此不能请求该文件"问题处理

    手里一个项目重新编译后发布,访问时提示未预编译文件“default.aspx”, 因此不能请求该文件.综合网上的解决方法,做了如下操作: 1.重新安装了AJAX Extension: 2.项目添加引用 ...

  7. struts2 学习日记1

    struts2 简介 struts2的前身可以说是framework.strut1作为当时很流行的框架,但是有很多的不足之处,framework出生后,它带来了很好的框架,但是很多人已经习惯了stru ...

  8. 本机连接调试Erlang结点与rebar3编译

    今天需要实时查看目标结点上的相关信息,于是查阅了关于远程Shell使用的资料,最终采用JCL的方式与本机上的erlang结点交互.在使用erl shell时需要指定目标结点的cookie以及当前结点名 ...

  9. codeforces 664C C. International Olympiad(数学)

    题目链接: C. International Olympiad time limit per test 1 second memory limit per test 256 megabytes inp ...

  10. SPOJ(后缀数组求不同子串个数)

    DISUBSTR - Distinct Substrings Given a string, we need to find the total number of its distinct subs ...