观察复杂度,是log级别以下回答询问的。

O(1)?逗我kx呢?

自然而然地想到线段树。

学长讲的原题啊考场上还不会打。

线段树上的每个节点都表示一个操作区间。

线段树上维护的权值有3个:这个子区间一共“净”加了多少层cnt,多少量num,以及它需要除掉前面的多少层del。

因为对于每一个子区间,它只可能有几种情况:

新累加了几层,或者这个子区间不够删了删前面的几层,或先删掉前面的几层再加上新的几层。

那么每个叶节点就不用说啦,关键就在于两个区间合并。

1,如果右区间要删左区间而且还能把它删干净,那么整个区间要删的量就是del[r]+del[l]-cnt[l],整个区间累加的量就是右区间所累加的

2,如果删了但没删干净,那么我们就需要删掉左区间里最靠后的几个没被删除的值,删除量就是左区间的删除量,剩余层数就是cnt[l]+cnt[r]-del[r]

但是怎么知道那“最靠后的几个值”呢?

稍微改变一下设问,查询线段树子树中区间内最后几个有权值位置的权值和。打个ask函数就好了。

然而这里有一个易错点:你不能直接查询左子树的最靠后的那几个值,因为右子树可能删除了它的一部分。

所以你要查询的是p子树的后k个的话,实际上就是ask(p,k+del[bro])-ask(p,del[bro])

bro是指p的右兄弟。如果p本身就是右子树则不存在。这样被它右子树删除的元素就被我们考虑到了。

然后就到了考验码力的时候了。

 #include<bits/stdc++.h>
using namespace std;
#define lc p<<1
#define rc p<<1|1
int opt[],k[],num[],cnt[],del[],n,m,cl[],cr[];
int ask(int p,int t){
if(!t)return ;
if(cnt[p]<=t)return num[p];
if(t<=cnt[rc])return ask(rc,t);
return ask(lc,t-cnt[rc]+del[rc])-ask(lc,del[rc])+num[rc];
}
void up(int p){
if(del[rc]>cnt[lc])del[p]=del[lc]+del[rc]-cnt[lc],cnt[p]=cnt[rc],num[p]=num[rc];
else del[p]=del[lc],cnt[p]=cnt[rc]+cnt[lc]-del[rc],num[p]=num[rc]+num[lc]-ask(lc,del[rc]);
}
void build(int p,int l,int r){
cl[p]=l;cr[p]=r;
if(l==r){
if(opt[l])del[p]=k[l];
else cnt[p]=,num[p]=k[l];
return;
}
build(lc,l,l+r>>);build(rc,(l+r>>)+,r);up(p);
}
void change(int p,int x){
if(cl[p]==cr[p]){
if(opt[x])del[p]=k[x],cnt[p]=num[p]=;
else cnt[p]=,num[p]=k[x],del[p]=;
return;
}
if(cl[rc]<=x)change(rc,x);else change(lc,x);up(p);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)scanf("%d%d",&opt[i],&k[i]);
build(,,n);
for(int i=,x;i<=m;++i){
scanf("%d",&x);scanf("%d%d",&opt[x],&k[x]);
change(,x);printf("%d\n",num[]);
}
}

就1.1k但都是精华

Weed:线段树的更多相关文章

  1. 【Foreign】Weed [线段树]

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

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

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

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

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

  4. [CSP-S模拟测试]:Weed(线段树)

    题目描述 $duyege$的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹.为了查出真相,$duyege$准备修好电脑之后再进行一次金坷垃的模拟实验.电脑上面有若干层金坷垃,每次只能在上面撒上一层高度 ...

  5. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  6. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  7. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  8. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  9. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

随机推荐

  1. scalikejdbc 学习笔记(4)

    Batch 操作 import scalikejdbc._ import scalikejdbc.config._ object BatchOperation { def main(args: Arr ...

  2. .NET进阶篇-语言章-2-Delegate委托、Event事件

    知识只有经过整理才能形成技能 整个章节分布简介请查看第一篇 内容目录 一.概述 二.解析委托知识点 1.委托本质 2.委托的使用 3.委托意义 逻辑解耦,减少重复代码 代码封装支持扩展 匿名方法和La ...

  3. javascript DOM节点

    获得子节点方式: 1.将文本内容也当成节点 childNodes firstChild lastChild 2.获得标签为内容的节点 children firstElementChild lastEl ...

  4. 使用foreach语句对数组成员进行遍历

    /*** 使用foreach语句对数组成员进行遍历* **/ public class ForeachDemo { public static void main(String[] args) { i ...

  5. Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 10.x

    运行Reac项目报: Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js ...

  6. Mac 10.14在新窗口中打开文件夹

    Mac 10.14 Open folders in new window (high Sierra) System Preferences > Dock. Change "Prefer ...

  7. 神奇的Java僵尸(defunct)进程问题排查过程

    现象描述 大概1个月多以前 在启动脚本中增加了tail -f 用来启动后追踪日志判断是否启动成功 后发现无法执行shutdown.sh(卡住 利用curl) 然后无奈使用kill -9 但通过ps - ...

  8. python selenium句柄操作

    一.获取当前窗口句柄 1.元素有属性,浏览器的窗口其实也有属性的,只是你看不到,浏览器窗口的属性用句柄(handle)来识别. 2.人为操作的话,可以通过眼睛看,识别不同的窗口点击切换.但是脚本没长眼 ...

  9. 程序猿的产品思考:2C与2B产品思维的区别

    原创/朱季谦   我最早接触到互联网产品的时候,听到最多的,是做产品要有用户思维,即站在用户角度去看待产品.这个先入为主的概念,在很长一段时间里,都被我效作经典.然而也在很长一段时间里,我竟混淆了其中 ...

  10. [USACO10NOV]奶牛的图片Cow Photographs

    题目描述 Farmer John希望给他的N(1<=N<=100,000)只奶牛拍照片,这样他就可以向他的朋友炫耀他的奶牛. 这N只奶牛被标号为1..N. 在照相的那一天,奶牛们排成了一排 ...