【Foreign】Weed [线段树]
Weed
Time Limit: 20 Sec Memory Limit: 512 MB
Description
从前有个栈,一开始是空的。
你写下了 m 个操作,每个操作形如 k v :
若 k = 0,代表往栈顶加入一个数 v
若 k = 1,则代表从栈顶弹出 v 个数,如果栈中的元素少于 v 个,则全部弹出。
接着你又进行了 q 次修改,每次你会选择一个操作,并且修改它的两个参数。
在每次修改后,你都要求出如果依次执行这些操作,最后栈中剩下的元素之和。
Input
第一行两个正整数 m,q,分别表示操作数和修改次数。
接下来 m 行,每行两个整数 k,v,代表一个操作。
接下来 q 行,每行三个正整数 c,k,v,表示将第 c 个操作的参数修改为 k 和 v。
Output
输出 q 行,每行一个整数,代表依次执行所有操作后栈中剩下的元素之和。
Sample Input
5 2
0 3
0 2
0 3
1 1
0 5
1 0 3
1 0 1
Sample Output
10
8
HINT
m,q ≤ 2×1e5, v ≤ 1e4
Solution
首先,我们可以把一个操作拆成:先删除若干个数,然后加入若干个数。
那么我们可以用线段树来维护,一个节点记录:删除del个数,加入add个数,这add个数的和是val。
那么我们只需要支持单点修改,答案显然就是Node[1].val。问题在于怎么合并两个节点的信息。
我们分情况讨论,记录左儿子为L,右儿子为R。显然信息形如:----+++ / -----+++。讨论一下 R.del 与 L.add 的关系:
1. 显然当 L.add <= R.del 的时候, del 即为 L.del + R剩余的del ,add 即为 R.add,val 即为 R.val;
2. 否则,当 L.add > R.del 的时候,难点在于 L 剩下多少 val,只要讨论出了这个问题,就解决了该题。
我们令函数 Query(i, k) 表示 删除了节点 i 的 后 k 个值,剩下的 val。那么显然这个也只要分类讨论即可:
1. k = R.add,返回 i.val - R.val 即可,比较显然;
2. k < R.add,显然我们需要继续往 R 递归,返回 i.val - R.val + Query(R, k);
3. k > R.add,显然我们需要往 L 递归,显然 k 先减去 R.add,又因为存在R.del这一段,所以 L 的后面几个是被删除的,要多查几个,所以返回 Query(L, k - R.add + R.del)。
然后我们写个线段树,就解决了这道题啦QWQ。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std;
typedef long long s64; const int ONE = 1e6 + ; int m, T; struct point
{
int opt, val;
}oper[ONE]; struct power
{
int add, del, val;
}Node[ONE * ]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} int Query(int i, int k)
{
int L = i << , R = i << | ;
if(k == Node[R].add) return Node[i].val - Node[R].val;
if(k < Node[R].add) return Node[i].val - Node[R].val + Query(R, k);
if(k > Node[R].add) return Query(L, k - Node[R].add + Node[R].del);
} power Merge(int L, int R)
{
power c = (power){, , };
if(Node[L].add <= Node[R].del)
c.del = Node[L].del + Node[R].del - Node[L].add,
c.add = Node[R].add, c.val = Node[R].val;
if(Node[L].add > Node[R].del)
{
c.del = Node[L].del;
c.add = Node[L].add - Node[R].del + Node[R].add;
c.val = Query(L, Node[R].del) + Node[R].val;
}
return c;
} void Build(int i, int l, int r)
{
if(l == r)
{
if(oper[l].opt == ) Node[i] = (power){, , oper[l].val};
else Node[i] = (power){, oper[l].val, };
return;
}
int mid = l + r >> ;
Build(i << , l, mid); Build(i << | , mid + , r);
Node[i] = Merge(i << , i << | ); } void Update(int i, int l, int r, int L)
{
if(L <= l && r <= L)
{
if(oper[l].opt == ) Node[i] = (power){, , oper[l].val};
else Node[i] = (power){, oper[l].val, };
return;
}
int mid = l + r >> ;
if(L <= mid) Update(i << , l, mid, L);
else Update(i << | , mid + , r, L);
Node[i] = Merge(i << , i << | );
} int main()
{
m = get(); T = get();
for(int i = ; i <= m; i++)
oper[i].opt = get(), oper[i].val = get();
Build(, , m);
while(T--)
{
int id = get();
oper[id].opt = get(); oper[id].val = get();
Update(, , m, id);
printf("%d\n", Node[].val);
}
}
【Foreign】Weed [线段树]的更多相关文章
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- Weed:线段树
观察复杂度,是log级别以下回答询问的. O(1)?逗我kx呢? 自然而然地想到线段树. 学长讲的原题啊考场上还不会打. 线段树上的每个节点都表示一个操作区间. 线段树上维护的权值有3个:这个子区间一 ...
- 【模拟8.10】Weed(线段树)
考试只好随便骗骗分过去啦啦啦..... 正解是玄学线段树: 以每个操作为叶子节点,我们定义几个变量ce表示层数,h表示高度,add表示所减的层数 那么问题转化为单点修改的问题输出直接是根节点答案 但是 ...
- 【Foreign】数据结构C [线段树]
数据结构C Time Limit: 20 Sec Memory Limit: 512 MB Description Input Output Sample Input Sample Output H ...
- 【Foreign】划分序列 [线段树][DP]
划分序列 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 9 4 ...
- 【Foreign】染色 [LCT][线段树]
染色 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output Sample Input 13 0 1 0 2 1 11 1 ...
- 【Foreign】阅读 [线段树][DP]
阅读 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 0 10 4 10 2 3 10 8 ...
- [CSP-S模拟测试]:Weed(线段树)
题目描述 $duyege$的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹.为了查出真相,$duyege$准备修好电脑之后再进行一次金坷垃的模拟实验.电脑上面有若干层金坷垃,每次只能在上面撒上一层高度 ...
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
随机推荐
- Alpha冲刺——第二天
Alpha第二天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...
- ACM 第十八天
数学基础(卷积,FFT,FWT,FMT,鸽巢原理,群论,哈里亚余数,哈里亚计数定理,组合数学,LVG定理,期望DP,期望点贡献问题) 练习题: A - Necklace of Beads Beads ...
- ajax与servlet交互(通过JSON),JAVA的arraylist传到前端的方法
所实现的效果:首先从前端(ajax)传参数给servlet,然后servlet经过处理,把arraylist类型的参数以JSON字符串的形式返回给前端(ajax),然后前端经过解析,把JSON字符串解 ...
- 查询MySQL某字段相同值得重复数据
1.先查询重复的id: SELECT book_id,COUNT(*) AS COUNT FROM xs_book_source WHERE site_id=5 GROUP BY book_id HA ...
- SpringBoot2.0(四) 远程调试
和tomcat远程调试近似的配置,主要的配置如下所示: -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=10009 在 ...
- 【python】python字符串前面加u,r,b的含义
1.字符串前加 u 例:u"我是含有中文字符组成的字符串." 作用:后面字符串以 Unicode 格式 进行编码,一般用在中文字符串前面,防止因为源码储存格式问题,导致再次使用时出 ...
- Matlab 之 im2col 【转】
函数原型: B=im2col(A,[m n],block_type) 功能:将矩阵A分为m×n的子矩阵,再将每个子矩阵作为B的一列 (1)当block_type为distinct时,将A分解为互不重叠 ...
- hdu 2768 Cat vs. Dog (二分匹配)
Cat vs. Dog Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- [SDOI2014][BZOJ3533] 向量集 [线段树+凸包]
题面 BZOJ传送门 思路 首先当然是推式子 对于一个询问点$(x_0,y_0$和给定向量$(x_1,y_1)$来说,点积这么表达: $A=x_0x_1+y_0y_1$ 首先肯定是考虑大小关系:$x_ ...
- [JLOI2014]松鼠的新家 树上差分
差分 一开始竟然想分情况讨论来差分,然后发现各自情况要分析, 就是为了解决中间节点重复计算的问题, 结果 最后一想,中间重复计算了一次,那我最后减掉不就好了么,,, 那这就是一道差分裸题了(这是唯一不 ...