[CSP-S模拟测试]: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$代表被更改的操作是第$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\leqslant 1,000,q\leqslant 1,000$。
对于另外$20%$的数据,每次$k=1$时都会将金坷垃清空。
对于$100%$的数据,$m\leqslant 2\times {10}^5,q\leqslant 2\times {10}^5,v_i\leqslant {10}^4$。
题解
首先,来解释一下题意,在更改操作之后就不改回来啦。
$30%$算法:
暴力修改,每次都暴力扫一遍统计答案。
时间复杂度:$\Theta(m\times q)$。
期望得分:$30$分。
实际得分:$30$分。
$100%$算法:
利用线段树维护以下四个值:
$\alpha.$区间内加数总和$sum$。
$\beta.$当前区间向前删除数字的数量$del$。
$gamma.$当前区间内“净”加的元素数$add$。
$delta.$当前区间被右兄弟删除后的总和$fla$(只对左儿子维护这个信息即可)。
每次询问就是输出$sum[1]$。
之后就是代码实现的问题了,主要是$pushup$函数比较难搞。
时间复杂度:$\Theta(N\log N+Q\log^2N)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
$30%$算法:
#include<bits/stdc++.h>
using namespace std;
int m,q;
pair<bool,int> e[200001];
int sta[200001],top;
int ans;
int main()
{
scanf("%d%d",&m,&q);
for(int i=1;i<=m;i++)
scanf("%d%d",&e[i].first,&e[i].second);
while(q--)
{
ans=0;
top=0;
int c,k,v;
scanf("%d%d%d",&c,&k,&v);
e[c]=make_pair(k,v);
for(int i=1;i<=m;i++)
if(e[i].first==1)for(int j=1;j<=e[i].second;j++)if(top)top--;else break;
else sta[++top]=e[i].second;
for(int i=1;i<=top;i++)ans+=sta[i];
printf("%d\n",ans);
}
return 0;
}
$100%$算法:
#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
int m,q;
int c,k,v;
pair<bool,int> e[200001];
int tradd[1000000],trdel[1000000],trfla[1000000],trsum[1000000];
int ask(int x,int w)
{
if(w<tradd[R(x)])return trfla[L(x)]+ask(R(x),w);
if(w==tradd[R(x)])return trfla[L(x)];
if(w>tradd[R(x)])return ask(L(x),w-tradd[R(x)]+trdel[R(x)]);
}
void pushup(int x)
{
if(tradd[L(x)]<=trdel[R(x)])
{
trfla[L(x)]=0;
tradd[x]=tradd[R(x)];
trdel[x]=trdel[L(x)]+trdel[R(x)]-tradd[L(x)];
trsum[x]=trsum[R(x)];
}
else
{
if(trdel[R(x)])trfla[L(x)]=ask(L(x),trdel[R(x)]);
else trfla[L(x)]=trsum[L(x)];
tradd[x]=tradd[L(x)]+tradd[R(x)]-trdel[R(x)];
trdel[x]=trdel[L(x)];
trsum[x]=trfla[L(x)]+trsum[R(x)];
}
}
void build(int x,int l,int r)
{
if(l==r)
{
if(e[l].first)trdel[x]=e[l].second;
else
{
tradd[x]=1;
trsum[x]=e[l].second;
trfla[x]=e[l].second;
}
return;
}
int mid=(l+r)>>1;
build(L(x),l,mid);
build(R(x),mid+1,r);
pushup(x);
}
void clear(int x){tradd[x]=trdel[x]=trsum[x]=trfla[x]=0;}
void change(int x,int l,int r,int w)
{
if(l==r)
{
clear(x);
if(e[l].first)trdel[x]=e[l].second;
else
{
tradd[x]=1;
trsum[x]=e[l].second;
trfla[x]=e[l].second;
}
return;
}
int mid=(l+r)>>1;
if(w<=mid)change(L(x),l,mid,w);
else change(R(x),mid+1,r,w);
pushup(x);
}
int main()
{
scanf("%d%d",&m,&q);
for(int i=1;i<=m;i++)
scanf("%d%d",&e[i].first,&e[i].second);
build(1,1,m);
while(q--)
{
scanf("%d%d%d",&c,&k,&v);
e[c]=make_pair(k,v);
change(1,1,m,c);
printf("%d\n",trsum[1]);
}
return 0;
}
rp++
[CSP-S模拟测试]:Weed(线段树)的更多相关文章
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】
题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...
- [CSP-S模拟测试]:影魔(树状数组+线段树合并)
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
- 【模拟8.10】Weed(线段树)
考试只好随便骗骗分过去啦啦啦..... 正解是玄学线段树: 以每个操作为叶子节点,我们定义几个变量ce表示层数,h表示高度,add表示所减的层数 那么问题转化为单点修改的问题输出直接是根节点答案 但是 ...
- BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分
题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...
- 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)
传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码
- 【Foreign】Weed [线段树]
Weed Time Limit: 20 Sec Memory Limit: 512 MB Description 从前有个栈,一开始是空的. 你写下了 m 个操作,每个操作形如 k v : 若 k ...
- CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】
正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...
随机推荐
- linux 安装telnet、curl、ifconfig、vim、ping等工具
1.首先执行下面命令更新相关源 apt-get update 2.安装telnet apt-get install telnet 3.安装curl apt-get install curl 4.安装i ...
- C#将字符串格式化为Json
private string ConvertStringToJson(string str) { //格式化json字符串 JsonSeria ...
- 【强化学习】MOVE37-Introduction(导论)/马尔科夫链/马尔科夫决策过程
写在前面的话:从今日起,我会边跟着硅谷大牛Siraj的MOVE 37系列课程学习Reinforcement Learning(强化学习算法),边更新这个系列.课程包含视频和文字,课堂笔记会按视频为单位 ...
- [Scala] java使用scala的jar包问题:Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Short
场景 刚写的scala处理bmp文件的实验, 打了jar包让java调用一下, 结果发生这个错误. package org.tanglizi.bmp.demo; import org.tanglizi ...
- Centos7:Redis3.0集群搭建
Redis集群中至少应该有三个节点.要保证集群的高可用,需要每个节点有一个备份机.Redis集群至少需要6台服务器. 搭建伪分布式.可以使用一台虚拟机运行6个redis实例. 修改redis的端口号7 ...
- ui组件库
基于Vue的Quasar Framework 中文网 http://www.quasarchs.com/ quasarframework/quasar: Quasar Frameworkhttps:/ ...
- python 访问权限
访问权限 权限: 公有的:类中的普通属性和方法,默认都是公有的,可以在类的内部.外部.子类中使用 私有的:定义是在前面加两个'_',只能在本类的内部使用,不能再外部及子类中使用 示例: class P ...
- js多语言切换demo
网站为了国际化的需要,会使用到语言包,案例如下图. 这次尝试用js来打语言包,用到了插件 jquery.i18n.properties ,很明显,使用这个插件需要先加载jquery. 代码布局结构 ...
- 阿里云环境中配置tomcat7可能出现的问题及解决方法
前提是安装好了tomcat,但是输入ip+端口无法访问,那么情况有一下几种 (1)可能防火墙没有关闭 systemctl stop firewalld.service #停止firewall syst ...
- python 列表字典按照字典中某个valu属性进行排序
对用户名进行排序 1. 直接上代码 base_dn_list = [ {', 'tenant': 'HAD', 'role': {'roleID': 'project', 'roleName': '项 ...