题目描述

$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(线段树)的更多相关文章

  1. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

  2. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  3. 【8.26校内测试】【重构树求直径】【BFS模拟】【线段树维护DP】

    题目性质比较显然,相同颜色联通块可以合并成一个点,重新建树后,发现相邻两个点的颜色一定是不一样的. 然后发现,对于一条链来说,每次把一个点反色,实际上使点数少了2个.如下图 而如果一条链上面有分支,也 ...

  4. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  5. 【模拟8.10】Weed(线段树)

    考试只好随便骗骗分过去啦啦啦..... 正解是玄学线段树: 以每个操作为叶子节点,我们定义几个变量ce表示层数,h表示高度,add表示所减的层数 那么问题转化为单点修改的问题输出直接是根节点答案 但是 ...

  6. BZOJ2040[2009国家集训队]拯救Protoss的故乡——模拟费用流+线段树+树链剖分

    题目描述 在星历2012年,星灵英雄Zeratul预测到他所在的Aiur行星在M天后会发生持续性暴雨灾害,尤其是他们的首都.而Zeratul作为星灵族的英雄,当然是要尽自己最大的努力帮助星灵族渡过这场 ...

  7. 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)

    传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码

  8. 【Foreign】Weed [线段树]

    Weed Time Limit: 20 Sec  Memory Limit: 512 MB Description 从前有个栈,一开始是空的. 你写下了 m 个操作,每个操作形如 k v : 若 k ...

  9. CF280D-k-Maximum Subsequence Sum【模拟费用流,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/CF280D 题目大意 一个长度为\(n\)的序列,\(m\)次操作 修改一个数 询问一个区间中选出\(k\)段不交子 ...

随机推荐

  1. [C#.net]xlApp.Workbooks.Open打开无法远程访问

    上月还能使用的xlApp.Workbooks.Open,这个月报无法远程访问,搞了半天,才找到原因是Foxit PDF 的Execl插件搞的鬼,记录下 Excel.Workbooks wbChecks ...

  2. wpf GeometryDrawing 绘制文字

    <GeometryDrawing x:Key="GeometryDrawingText"> <GeometryDrawing.Geometry> <R ...

  3. 爬虫时安装的newspaper 新闻包

    Newspaper3k: Article scraping & curation 首先在命令行安装 newspaper pip install Newspaper3k 然后导入包进行写代码 f ...

  4. ObjectMapper用于将java对象转换为json格式数据以及JSONObject对象解析json格式数据

    ObjectMapper objectMapper = new ObjectMapper(); //反序列化的时候如果多了其他属性,不抛出异常 objectMapper.configure(Deser ...

  5. lumen时区

    今天用 Lumen 框架写代码时, 也是初次体验 Lumen, 遇到了一个问题, 从数据库里查出的时间比数据库里保存的 TIMESTAMP 时间慢了8个小时, 很明显这是一个时区设置的问题, 本以为可 ...

  6. win10 修改文件夹右击默认打开程序

    1.注册表打开 cmd  regedit 2.打开如下位置 3.编辑图中2个Anycode.command的值 为打开 保存即可

  7. three.js之让物体动起来方式(一)移动摄像机

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. MYSQL获得查询记录的行号

    对于获得查询记录的行号这一功能,Oracle 中可以使用标准方法(8i版本以上),也可以使用非标准的ROWNUM,MS SQL Server 则在 2005 版本中提供了ROW_NUMBER()函数. ...

  9. kotlin递归&尾递归优化

    递归: 对于递归最经典的应用当然就是阶乘的计算啦,所以下面用kotlin来用递归实现阶乘的计算: 编译运行: 那如果想看100的阶乘是多少呢? 应该是结果数超出了Int的表述范围,那改成Long型再试 ...

  10. QT一个最简单的openGL例子

    创建一个基类为widget的工程 把文件夹glut64放到代码目录下,文件夹包含以下文件 freeglut.dll freeglut.lib glut.h freeglut.h freeglut_ex ...