【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秒开始,在第 ...
随机推荐
- Calculator Part Ⅰ
GitHub/object-oriented The title of the work 关于这次的作业,一开始我是觉得不难的,毕竟学长在已经提供了足够多的提示,实现步骤.需要那些方面的知识等等.但是 ...
- [基于NetCore的简单博客系统]-登录
0-项目背景 一个基于.NET CORE RAZOR PAGES的简单博客系统 技术栈全部采用微软官方实现方式,目的是熟悉新技术 项目地址:https://github.com/ganqiyin/BL ...
- HDU 5816 Hearthstone 概率dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5816 Hearthstone Time Limit: 2000/1000 MS (Java/Othe ...
- <Effective C++>读书摘要--Accustoming Youself to C++
<Item 1>View C++ as a federation of languages. 1.把C++看成4种子语言组成,即C.Object-Oriented C++.Template ...
- Web服务器性能压力测试工具
一.http_load 程序非常小,解压后也不到100K http_load以并行复用的方式运行,用以测试web服务器的吞吐量与负载. 但是它不同于大多数压力测试工具,它可以以一个单一的进程运行,一般 ...
- [OS] 多线程--第一次亲密接触CreateThread与_beginthreadex本质区别
转自:http://blog.csdn.net/morewindows/article/details/7421759 本文将带领你与多线程作第一次亲密接触,并深入分析CreateThread与_be ...
- hadoop的第一个hello world程序(wordcount)
在hadoop生态中,wordcount是hadoop世界的第一个hello world程序. wordcount程序是用于对文本中出现的词计数,从而得到词频,本例中的词以空格分隔. 关于mapper ...
- 【题解】CF#855 G-Harry Vs Voldemort
个人感觉挺有意思的,然而被颜神D无聊惹(- ̄▽ ̄)- 这题我们可以首先试图去统计以每一个点作为 w 点所能对答案造成的贡献是多少.不难发现,当且仅当 u 和 v 都在 w 所在边双的一侧的时候不能构成 ...
- [WC2005]双面棋盘
description 洛谷 给出一个\(n\times n\)的黑白棋盘. \(m\)次操作,每次将一个格子进行颜色翻转,求每次操作后的黑白四连通块数. data range \[n\le 200, ...
- bzoj 2424: [HAOI2010]订货 (费用流)
直接费用流,天数就是点数 type arr=record toward,next,cap,cost:longint; end; const maxm=; maxn=; mm=<<; var ...