联赛模拟测试20 C. Weed
题目描述
\(duyege\) 的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹。
为了查出真相,\(duyege\) 准备修好电脑之后再进行一次金坷垃的模拟实验。
电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为 \(v_i\)的金坷垃
或者除掉最新\(v_i\) 层(不是量)撒的金坷垃。如果上面只留有不足\(v_i\) 层金坷垃,那么就相当于电脑上面没有金坷垃了。
\(duyege\) 非常严谨,一开始先给你 \(m\) 个上述操作要你依次完成。
然后又对实验步骤进行了\(q\)次更改,每次更改都会改变其中一个操作为另外一个操作。
每次修改之后都会询问最终金坷垃的量有多少。
输入格式
输入第一行为两个正整数\(m\)、\(q\) ,接下来 \(m\) 行每行\(2\) 个整数 \(k\)、\(v_i\) 。 \(k\)为 \(0\)时撒金坷垃,为\(1\) 时除金坷垃。
接下来\(q\) 行每行\(3\) 个整数 \(c_i\)、\(k\) 、\(v_i\) , 代表被更改的操作是第 \(c_i\) 个,
后面\(2\)个数描述更改为这样的操作。
输出格式
输出\(q\)行代表每次金坷垃的量为多少
样例
样例输入
10 5
0 10
1 5
0 13
0 18
0 2
1 1
0 8
0 9
1 3
0 7
9 0 3
10 1 7
6 0 8
10 0 5
8 1 2
样例输出
58
0
0
66
41
数据范围与提示
对于 \(30\%\)的数据,\(m \leq 1000,q \leq 1000\)
.
对于另外 \(20\%\) 的数据,每次\(k=1\) 时都会将金坷垃清空。
对于 100%的数据,\(m \leq 2 \times 10^5,q \leq 2 \times 10^5,v_i \leq 10^4\) .
分析
考场上 \(20\) 分暴力打挂,只因一个 \(continue\)
for(rg int i=1;i<=q;i++){
aa=read(),bb=read(),cc=read();
if(b[aa].op==0){
if(bb==0){
ad(aa,-b[aa].val);
ad(aa,cc);
} else {
now=cx(aa)-cx(aa-1);
ad(aa,-now);
xg(1,aa,aa);
}
} else {
if(bb) continue;
else {
xg(1,aa,0);
ad(aa,cc);
}
}
b[aa].op=bb,b[aa].val=cc;
now=shu[1].mmin;
if(now==0) printf("%d\n",cx(m));
else printf("%d\n",cx(m)-cx(now));
}
for(rg int i=1;i<=q;i++){
aa=read(),bb=read(),cc=read();
if(b[aa].op==0){
if(bb==0){
ad(aa,-b[aa].val);
ad(aa,cc);
} else {
now=cx(aa)-cx(aa-1);
ad(aa,-now);
xg(1,aa,aa);
}
} else {
if(!bb) {
xg(1,aa,0);
ad(aa,cc);
}
}
b[aa].op=bb,b[aa].val=cc;
now=shu[1].mmin;
if(now==0) printf("%d\n",cx(m));
else printf("%d\n",cx(m)-cx(now));
}
正解用线段树维护
每个点记录三个值:执行完这段操作后会删多少个,再插多少个,插的和一共是多少
合并值时再用一个函数查找左孩子被从右删除若干个后剩下的插入总和是多少
注意查找时,如果右儿子的层数大于清除的层数
应该写成
return tr[da].sum-tr[da<<1|1].sum+cx(da<<1|1,cnt);
而不是
return tr[da<<1].sum+cx(da<<1|1,cnt);
比如这样的数据('-'代表删除)
++++ -+++
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e6+5;
int m,q;
struct asd{
int op,val;
asd(){}
asd(int aa,int bb){
op=aa,val=bb;
}
}b[maxn];
struct trr{
int l,r,sum,cnt,del;
}tr[maxn];
int cx(int da,int cnt){
if(tr[da<<1|1].cnt==cnt){
return tr[da].sum-tr[da<<1|1].sum;
} else if(tr[da<<1|1].cnt>cnt){
return tr[da].sum-tr[da<<1|1].sum+cx(da<<1|1,cnt);
} else {
return cx(da<<1,cnt-tr[da<<1|1].cnt+tr[da<<1|1].del);
}
}
void push_up(int da){
if(tr[da<<1|1].del>tr[da<<1].cnt){
tr[da].del=tr[da<<1].del+tr[da<<1|1].del-tr[da<<1].cnt;
tr[da].cnt=tr[da<<1|1].cnt;
tr[da].sum=tr[da<<1|1].sum;
} else if(tr[da<<1|1].del==0){
tr[da].del=tr[da<<1].del;
tr[da].sum=tr[da<<1].sum+tr[da<<1|1].sum;
tr[da].cnt=tr[da<<1].cnt+tr[da<<1|1].cnt;
} else {
tr[da].del=tr[da<<1].del;
tr[da].cnt=tr[da<<1].cnt+tr[da<<1|1].cnt-tr[da<<1|1].del;
if(tr[da<<1].cnt==tr[da<<1|1].del) tr[da].sum=tr[da<<1|1].sum;
else tr[da].sum=tr[da<<1|1].sum+cx(da<<1,tr[da<<1|1].del);
}
}
void build(int da,int l,int r){
tr[da].l=l,tr[da].r=r;
if(tr[da].l==tr[da].r){
if(b[l].op==1){
tr[da].del=b[l].val;
} else {
tr[da].cnt=1;
tr[da].sum=b[l].val;
}
return;
}
rg int mids=(tr[da].l+tr[da].r)>>1;
build(da<<1,l,mids);
build(da<<1|1,mids+1,r);
push_up(da);
}
void xg(int da,int wz){
if(tr[da].l==tr[da].r){
if(b[wz].op==1){
tr[da].del=b[wz].val;
tr[da].cnt=tr[da].sum=0;
} else {
tr[da].del=0;
tr[da].cnt=1;
tr[da].sum=b[wz].val;
}
return;
}
rg int mids=(tr[da].l+tr[da].r)>>1;
if(wz<=mids) xg(da<<1,wz);
else xg(da<<1|1,wz);
push_up(da);
}
int main(){
freopen("weed.in","r",stdin);
freopen("weed.out","w",stdout);
m=read(),q=read();
for(rg int i=1;i<=m;i++){
b[i].op=read(),b[i].val=read();
}
build(1,1,m);
rg int aa,bb,cc;
for(rg int i=1;i<=q;i++){
aa=read(),bb=read(),cc=read();
b[aa].op=bb,b[aa].val=cc;
xg(1,aa);
printf("%d\n",tr[1].sum);
}
return 0;
}
联赛模拟测试20 C. Weed的更多相关文章
- [考试反思]0813NOIP模拟测试20
咕了两天,补一下. 4个AK的,210是第10,190的第15并列一大排,我个傻子160排第29. 历史新低,但是心态还好. 真是没想到会一天考两场.中午没回去睡觉晚上考试... 困倒是其次,关键还是 ...
- 8.10 NOIP模拟测试16 Blue+Weed+Drink
T1 Blue 贪心,每次跳得时候跳能跳到的最远的地方,跳过的就把他设为0,每次二分找到位置,一直跳就行,如果能跳到的位置就是当前位置或比当前位置还小(数组里现在呆着的这一块石头,二分得到的就是当前位 ...
- 联赛模拟测试10 C. 射手座之日
题目描述 分析 方法一(线段树) 线段树维护的是以当前节点为左端点的区间的贡献 而区间的右端点则会从 \(1\) 到 \(n\) 逐渐右移 当我们把右端点从 \(i-1\) 的位置扩展到 \(i\) ...
- 联赛模拟测试17 A. 简单的区间 启发式合并
题目描述 分析 我们要找的是一段区间的和减去该区间的最大值能否被 \(k\) 整除 那么对于一段区间,我们可以先找出区间中的最大值 然后枚举最大值左边的后缀与最大值右边的前缀之和是否能被 \(k\) ...
- 联赛模拟测试18 A. 施工 单调队列(栈)优化DP
题目描述 分析 对于 \(Subtask\ 1\),可以写一个 \(n^3\) 的 \(DP\),\(f[i][j]\) 代表第 \(i\) 个建筑高度为 \(j\) 时的最小花费,随便转移即可 时间 ...
- 联赛模拟测试24 B. 答题 折半枚举
题目描述 分析 暴力的思想是把 \(2^n\) 种得分枚举出来,每一种得分的概率都是相同的,然后从小到大累加,直到大于等于所给的概率 把问题转化一下,就变成了在 \(2^n\) 种元素中求 \(k\) ...
- noip模拟测试20
考试总结:这次考试,我非常真实地感觉到了自己能力的提高,具体来说,在之前的考试中,读完题之后我只会想到暴力的思路,甚至有的题连暴力都打不出来,但是这次在考场上我已经有了自己的一些想法,有了一个深入思考 ...
- 联赛模拟测试5 涂色游戏 矩阵优化DP
题目描述 分析 定义出\(dp[i][j]\)为第\(i\)列涂\(j\)种颜色的方案数 然后我们要解决几个问题 首先是求出某一列涂恰好\(i\)种颜色的方案数\(d[i]\) 如果没有限制必须涂\( ...
- 联赛模拟测试8 Dash Speed 线段树分治
题目描述 分析 对于测试点\(1\).\(2\),直接搜索即可 对于测试点\(3 \sim 6\),树退化成一条链,我们可以将其看成序列上的染色问题,用线段树维护颜色相同的最长序列 对于测试点\(7\ ...
随机推荐
- 老生常谈SpringAop日志收集与处理做的工具包
AopLog是基于Spring Aop 和ThreadLocal实现的一个专门对请求方法内容日志的拦截与处理的日志工具包. 场景 : 我想知道一些重要的请求方法的请求参数,响应参数,请求头,以及耗时, ...
- Dockerfile构建镜像实战
目录 一.常见Dockerfile指令 二.编写Centos Dockerfile 2.1.编写Dockerfile 2.2.构建 2.3.查看Docker镜像 2.4.运行镜像 三.CMD和ENTR ...
- Linux实战(20):Docker部署EKL入门环境记录文档
安装环境: centos7 ,EKL全套为7.5.2版本 前期工作 拉取已下三个镜像 docker.io/logstash 7.5.2 b6518c95ed2f 6 months ago 805 MB ...
- python中的方向控制函数
方向控制函数:控制海龟方向,包含绝对角度&海龟角度 改变海龟运行方向,让海龟转向 angle :改变行进方向,将海归运行方向改变为某一个绝对的角度 例如 将坐标系中的海龟方向改变为绝对系中的4 ...
- 学习使用PSTools工具中的psping
目录 初识PsTools psping 1.使用ICMP ping 2.使用TCP ping 3.延迟测试 4.带宽测试 5.同功能的tcping工具 总结 初识PsTools 在工作中我们都 ...
- 登录、认证、token处理、前台cookie存储token
免费课程相关表设计 models的设计 from django.contrib.contenttypes.fields import GenericRelation class Course(mode ...
- python数据结构实现(栈和链栈)
栈 class Stack: def __init__(self, limit: int 10): self.stack = [] self.limit = limit def __bool__(se ...
- Spring学习(十)--Spring的AOP
1.Spring AOP拦截器 (1)设计原理 Spring AOP在通过JDK的Proxy或者CGLIB方式生成代理对象的时候,拦截器的相关信息就配置到代理对象中了. 1)如果使用JDK的Proxy ...
- P4279 [SHOI2008]小约翰的游戏(Anti_nim)
Link 题面 题目描述 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有 \(n\) 堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子, 在这堆石子中取走任意多的石子,但不 ...
- 【题解】[SDOI2016]征途
Link 题目大意:给定序列,将它划分为\(m\)段使得方差最小,输出\(s^2*m^2\)(一个整数). \(\text{Solution:}\) 这题我通过题解中的大佬博客学到了一般化方差柿子的写 ...