【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秒开始,在第 ...
随机推荐
- java日期格式处理
继承关系:java.lang.Object->java.text.Format->java.text.DateForm->java.text.SimpleDateFormat 日期代 ...
- c# 删除word文档中某一页
object objPage = 14; int pages = oDoc.ComputeStatistics(Microsoft.Office.Interop.Word.WdStatistic.wd ...
- Android 开发 之 JNI入门 - NDK从入门到精通
NDK项目源码地址 : -- 第一个JNI示例程序下载 : GitHub - https://github.com/han1202012/NDKHelloworld.git -- Java传递参数给C ...
- Android之Bluetooth编程
Android Bluetopth 编程大牛文章 http://my.oschina.net/u/994235/blog?catalog=313604 ViewGroup 相关资料 : http:// ...
- 最长回文子串计算(fail)
题意: 给定一个字符串s,在s中找到最长的回文子字符串.您可以假设s的最大长度为1000. 例子: 输入: “babad” 输出: “bab” 注: “aba”也是一个有效的答案. 我的答案: 想法: ...
- MFC消息处理
1.MFC窗口如何与AfxWndProc建立联系. 当一个新的CWnd派生类创建时,在调用CWnd::CreateEx()过程中,MFC都会安装AfxCbtFilterHook().这个Hook将拦截 ...
- TCP系列29—窗口管理&流控—3、Nagle算法
一.Nagle算法概述 之前我们介绍过,有一些交互式应用会传递大量的小包(称呼为tinygrams),这些小包的负载可能只有几个bytes,但是TCP和IP的基本头就有40bytes,如果大量传递这种 ...
- ejabberd学习2
1.ejabberd监听多个端口 每个网络连接进来,ejabberd都会使用一个进程来负责这个连接的数据处理.原理跟Joe Armstrong的<Erlang程序设计>中的并行服务器一样, ...
- 父类与子类的转换as,is
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 【bzoj3437】小P的牧场 斜率优化dp
题目描述 背景 小P是个特么喜欢玩MC的孩纸... 描述 小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这n个牧场,他需要在某些牧场上面建立控制站,每个 ...