【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秒开始,在第 ...
随机推荐
- OpenGL ES 2.0 -- 制作 3D 彩色旋转三角形 - 顶点着色器 片元着色器 使用详解
最近开始关注OpenGL ES 2.0 这是真正意义上的理解的第一个3D程序 , 从零开始学习 . 案例下载地址 : http://download.csdn.net/detail/han120201 ...
- com技术学习
百度百科概念 COM是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术.在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应 ...
- LintCode-5.第k大元素
第k大元素 在数组中找到第k大的元素 注意事项 你可以交换数组中的元素的位置 样例 给出数组 [9,3,2,4,8],第三大的元素是 4 给出数组 [1,2,3,4,5],第一大的元素是 5,第二大的 ...
- 无法启动此程序,因为计算机中丢失 zlibd.dll【OSG】
在配置OSG的过程中遇到了这个问题.记录一下. zlibd.dll这个DLL可以在第三方库3rdParty里面找到.找到之后复制到OSG的bin目录下即可.
- 【week3】词频统计 单元测试
使用Eclipse 集成的Junit进行单元测试.单元测试的核心包括断言.注解. 测试代码如下: @BeforeClass // 针对所有测试,只执行一次,且必须为static void public ...
- [CLR via C#]异常和状态管理
当CLR检测到某个正在运行的.NET应用程序处于一种特殊的正常执行顺序被打断的状态时,会生成一个异常对象来表示这个错误,并将此对象在方法调用堆栈中向上传送.如果一个程序引发了一个异常却没有处理,CLR ...
- Extensions disabled by Chrome
Extensions disabled by Chrome https://support.google.com/chrome_webstore/answer/2811969 https://supp ...
- [剑指Offer] 45.扑克牌顺子
题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决 ...
- FLT_MIN,FLT_MAX,FLT_EPSILON
FLT_MIN,FLT_MAX,FLT_EPSILON * min positive value */最小的正值#define FLT_MIN 1.175494351e-38F /* max val ...
- 【bzoj3297】[USACO2011 Open]forgot STL+dp
题目描述 发生了这么多,贝茜已经忘记了她cowtube密码.然而,她记得一些有用的信息. 首先,她记得她的密码(记为变量P)长度为L(1 <= L<=1,000)字符串,并可以被分成 一个 ...