jzoj5989. 【北大2019冬令营模拟2019.1.6】Forest (set)
题面

题解
为了一点小细节卡了一个下午……我都怕我瞎用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)的更多相关文章
- jzoj5990. 【北大2019冬令营模拟2019.1.6】Bear (状压dp)
题面 题解 我永远讨厌dp.jpg 搞了一个下午优化复杂度最后发现只要有一个小trick就可以A了→_→.全场都插头dp就我一个状压跑得贼慢-- 不难发现我们可以状压,对于每一行,用状态\(S\)表示 ...
- jzoj5991. 【北大2019冬令营模拟2019.1.6】Juice
题面 题解 好迷-- //minamoto #include<bits/stdc++.h> #define R register #define ll long long #define ...
- jzoj5984. 【北大2019冬令营模拟2019.1.1】仙人掌 (分块)
题面 题解 数据结构做傻了.jpg 考虑每一个节点,它的儿子的取值最多只有\(O(\sqrt {m})\)种,那么可以用一个双向链表维护儿子的所有取值以及该取值的个数,那么对儿子节点修改一个值就是\( ...
- jzoj5983. 【北大2019冬令营模拟2019.1.1】多边形 (组合数学)
这其实是道打表题--你看我代码就知道了-- 咳咳来点严谨证明好了-- 前方高能请注意 首先,正多边形近似于圆,可以看做在圆里内接多边形.圆内接多边形最多只有三个锐角.因为凸多边形的外角和为\(360\ ...
- JZOJ[5971]【北大2019冬令营模拟12.1】 party(1s,256MB)
题目 题目大意 给你一棵树,在树上的某一些节点上面有人,要用最小的步数和,使得这些人靠在一起.所谓靠在一起,即是任意两个人之间的路径上没有空的节点(也就是连在一起). N≤200N \leq 200N ...
- [JZOJ5977] 【清华2019冬令营模拟12.15】堆
题目 其中n,q≤500000n,q\leq 500000n,q≤500000 题目大意 让你维护一个堆.支持一下操作: 在某个点的下面加上另一个点,然后进行上浮操作. 询问某一点的权值. 思考历程 ...
- Visual Studio 2019 发布活动 - 2019 年 4 月 2 日
Visual Studio 2019 发布活动 2019 年 4 月 2 日,星期二 | 上午 9:00 (PT) 围观: https://visualstudio.microsoft.com/zh- ...
- [2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania
[2018冬令营模拟测试赛(二十一)]Problem A: Decalcomania 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见&quo ...
- jzoj6101. 【GDOI2019模拟2019.4.2】Path
题目链接:https://jzoj.net/senior/#main/show/6101 记\(f_i\)为从\(i\)号点走到\(n\)号点所花天数的期望 那么根据\(m\)条边等可能的出现一条和一 ...
随机推荐
- iOS 优化方案浅析
本文转载至 http://mobile.51cto.com/iphone-413256.htm Windows独特的注册表机制以及复杂的进程.内存管理,给了很多PC“优化”类软件极大的机遇,比如奇虎3 ...
- EasyIPCamera实现Windows PC桌面、安卓Android桌面同屏直播,助力无纸化会议系统
最近在EasyDarwin开源群里,有不少用户私信需求,要做一种能够多端同屏的系统,细分下来有屏幕采集端和同屏端,屏幕采集端细想也就是一个低延时的流媒体音视频服务器,同屏端也就是一个低延时的播放器,负 ...
- g++: command not found的解决
G++没有装或却没有更新 以下方法都可以试试: centos: yum -y update gcc yum -y install gcc+ gcc-c++ ubuntu: apt-get up ...
- 九度OJ 1104:整除问题 (整除、因式分解)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4142 解决:1346 题目描述: 给定n,a求最大的k,使n!可以被a^k整除但不能被a^(k+1)整除. 输入: 两个整数n(2< ...
- RecyclerView 可以与CollapsingToolbarLayout一起使用
Item 布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and ...
- 向HTML页面传入参数
这次是想将参数传入HTML页面,通过js获取参数信息,动态生成HTML页面内容: 方法一: <script> function GetArgsFromHref(sHref, sArgNam ...
- 使用grunt js进行js的链接和压缩
1,http://nodejs.org/download/ 安装nodejs 2,配置环境变量,将nodejs的安装目录放置在Path环境变量中 3,在cmd中 npm install -g grun ...
- Memory Notification: Library Cache Object loaded into SGA
问题现象: 数据库服务器可以ping通,但SSH连接不了:应用.plsqldeveloper 也都连接不了.事情到了这个地步,只能重启服务器. 服务器环境:oracle10.2.0.1 +rhel5. ...
- 【MongoDB学习-在.NET中的简单操作类】
1.新建MVC项目, 管理NuGet包,进入下载MongDB.net库文件 2.新增项目DAL数据访问层,引用以下库文件: 3.C# 访问MongoDB通用方法类: using MongoDB.Dri ...
- 【整理】XOR:从陌生到头晕
一:解决XOR常用的方法: 在vjudge上面输入关键词xor,然后按照顺序刷了一些题. 然后大概悟出了一些的的套路: 常用的有贪心,主要是利用二进制的一些性质,即贪心最大值的尽量高位取1. 然后有前 ...