题意

给出一个长度为 \(n\) 的序列 \(\{a_i\}\) , 现在会进行 \(m\) 次操作 , 每次操作会修改某个 \(a_i\) 的值 ,

在每次操作完后你需要判断是否存在一个位置 \(i\), 满足 \(\displaystyle a_i = \sum_{j=1}^{i - 1}a_j\) 并求任意一个 \(i\) .

\(n, m ≤ {10}^5 , 0 ≤ a_i ≤ {10}^9\)

题解

考虑一个暴力,不妨首先从 \(i = 1\) 开始判断是否合法,由于 \(a_i\) 是单调不降的,符合条件的 \(a_i\) 一定大于等于当前前缀和。

每次用线段树找到大于等于当前前缀和的最左边的 \(a_i\) 并判断是否合法。(这个位置一定要在前缀和的右边)

这样为什么是对的呢,因为你下一次的起点不可能存在与现在的位置到下次位置之间的任意位置。

(因为每个值都不会 \(\ge\) 当前的前缀和)

这样做就是对的了,因为如果新的 \(a_i​\) 不合法,那么当前前缀和至少会达到上一次的两倍。

于是这样子查找的次数就是 \(O(\log w)\) 的 , 总复杂度是 \(O(m \log n \log w)\) .

总结

考虑一类题对于权值翻倍时候的复杂度是 \(O(\log w)\) 的,例如 ZJOI2018 历史

代码

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__) using namespace std; template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;} inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
} void File() {
#ifdef zjp_shadow
freopen ("E.in", "r", stdin);
freopen ("E.out", "w", stdout);
#endif
} const int N = 2e5 + 1e3; typedef long long ll; #define lson o << 1, l, mid
#define rson o << 1 | 1, mid + 1, r int a[N]; template<int Maxn>
struct Segment_Tree { int maxv[Maxn]; ll sumv[Maxn]; inline void Push_Up(int o) {
sumv[o] = sumv[o << 1] + sumv[o << 1 | 1];
maxv[o] = max(maxv[o << 1], maxv[o << 1 | 1]);
} void Build(int o, int l, int r) {
if (l == r) return (void)(maxv[o] = sumv[o] = a[l]);
int mid = (l + r) >> 1; Build(lson); Build(rson); Push_Up(o);
} void Update(int o, int l, int r, int up, int uv) {
if (l == r) return (void)(sumv[o] = maxv[o] = uv);
int mid = (l + r) >> 1;
if (up <= mid) Update(lson, up, uv);
else Update(rson, up, uv); Push_Up(o);
} ll Sum(int o, int l, int r, int qr) {
if (r <= qr) return sumv[o];
int mid = (l + r) >> 1;
return Sum(lson, qr) + (qr > mid ? Sum(rson, qr) : 0);
} int Find(int o, int l, int r, int ql, ll val) {
if (ql > r || maxv[o] < val) return 0;
if (l == r) return l; int mid = (l + r) >> 1;
int pos = Find(lson, ql, val);
return pos ? pos : Find(rson, ql, val);
} }; Segment_Tree<N << 2> T; int n, q; inline int Solve() {
if (a[1] == 0) return 1;
int cur = 1; ll sum = a[1];
for (;;) {
int pos = T.Find(1, 1, n, cur + 1, sum);
if (!pos) return -1;
sum = T.Sum(1, 1, n, (cur = pos) - 1);
if (sum == a[pos]) return pos; sum += a[pos];
}
} int main () { File(); n = read(), q = read(); For (i, 1, n) a[i] = read();
T.Build(1, 1, n); For (i, 1, q) {
int pos = read(), val = read();
T.Update(1, 1, n, pos, a[pos] = val);
printf ("%d\n", Solve());
} return 0; }

Codeforces Round #489 (Div. 2) E. Nastya and King-Shamans(线段树)的更多相关文章

  1. Codeforces Round #489 (Div. 2) E - Nastya and King-Shamans

    E - Nastya and King-Shamans 题目大意:有n个数,每一次操作更改一个数,每次操作之后问你是否有一个数等于其前面所有数的和. 思路:好题,想了很久没想出来,看了题解,主要思想就 ...

  2. Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)

    题目链接:http://codeforces.com/contest/474/problem/F 题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数 ...

  3. Codeforces Round #332 (Div. 2) C. Day at the Beach 线段树

    C. Day at the Beach Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/599/p ...

  4. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  5. Codeforces Round #271 (Div. 2) F题 Ant colony(线段树)

    题目地址:http://codeforces.com/contest/474/problem/F 由题意可知,最后能够留下来的一定是区间最小gcd. 那就转化成了该区间内与区间最小gcd数相等的个数. ...

  6. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

  7. Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)

    题目链接:http://codeforces.com/problemset/problem/438/D 给你n个数,m个操作,1操作是查询l到r之间的和,2操作是将l到r之间大于等于x的数xor于x, ...

  8. Codeforces Round #320 (Div. 1) [Bayan Thanks-Round] B. "Or" Game 线段树贪心

    B. "Or" Game Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/578 ...

  9. Codeforces Round #530 (Div. 2)F Cookies (树形dp+线段树)

    题:https://codeforces.com/contest/1099/problem/F 题意:给定一个树,每个节点有俩个信息x和t,分别表示这个节点上的饼干个数和先手吃掉这个节点上一个饼干的的 ...

随机推荐

  1. 第十二届湖南省赛 A - 2016 ( 数学,同余转换)

    给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量:       1. 1≤a≤n,1≤b≤m;   2. a×b 是 2016 的倍数.   Input   输入包含不超过 30 ...

  2. Mike and strings CodeForces - 798B (又水又坑)

    题目链接 题意:英语很简单,自己取读吧. 思路: 既然n和i字符串的长度都很小,最大才50,那么就是只要能出答案就任意暴力瞎搞. 本人本着暴力瞎搞的初衷,写了又臭又长的200多行(代码框架占了50行) ...

  3. 关于微信小程序使用canvas生成图片,内容图片跨域的问题

    最近有个项目是保存为名片(图片),让用户发送给朋友或朋友圈,找了很多方案都不适用,绞尽脑汁之后还是选了使用canvas,但是用这玩意儿生成图片最大的缺点就是,如果你的内容中有图片,并且这个图片是通过外 ...

  4. [转帖]csdn windows 下载整理.

    特别说明:本帖不提供任何密钥或激活方法,请大家也不要在帖内回复或讨论涉及版权的相关内容,仅提供原版ISO下载链接 https://bbs.csdn.net/topics/391111024?list= ...

  5. mybatis异常解决:class path resource [SqlMapConfig.xml] cannot be opened because it does not exist

    解决方法: 缺失SqlMapConfig.xml文件.

  6. C# Note16: wpf window 中添加enter和双击事件

     一.添加回车(enter)事件 在C#编程时,有时希望通过按回车键,控件焦点就会自动从一个控件跳转到下一个控件进行操作. 以用户登录为例,当输入完用户名和密码后, 需要点击登录按钮,而登录按钮必须获 ...

  7. linux 依赖解决办法

    在安装软件过程中如果出现依赖不满足,有两种情况: 1:你系统里面没有安装依赖软件,[但是你的软件源里面有这个软件,你只是没有安装], 这种情况很简单,通过 sudo apt-get install - ...

  8. Simple Use IEnumerable<T>

    Private static IEnumerable<T> FunDemo(T para) { while(...) { .... yield return Obj; } } static ...

  9. 学习Linux系统的态度及技巧

    Linux作为一种简单快捷的操作系统,现在被广泛的应用.也适合越来越多的计算机爱好者学习和使用.但是对于Linux很多人可能认为很难,觉得它很神秘,从而对其避而远之,但事实真的是这样么?linux真的 ...

  10. 了解AutoCAD对象层次结构 —— 4 —— 符号表

    上一小节我们看到了符号表包含了一系列的表(共9个),这些表数量是固定的,用户不能增加新的表,也不能删除现有的表. 符号表名称 符号表功能 Block Table 块表 存储图形数据库中定义的块.此表中 ...