这是一道卡常好题

从160s卡到36s

qwq

由于题目设计到原数组的单点修改,那么就对应着前缀和数组上的区间加。

很显然能想到用线段树来维护这么个东西。

那么该如果求题目要求的位置呢

我们来看这个题的式子,他要求$$a_i = s_{i-1}$$

我们稍微变形一下$$s_i-s_{i-1}=s_{i-1}$$

\[s_i = 2\times s_{i-1}
\]

而且,由于\(a\)数组任意时刻都是非负的。所以\(s\)也是单调不下降的。

那我们就可以从\(1\)开始,然后每次找到第一个大于等于\(2*当前值\)的位置,看看是否合法,然后跳过去,继续下一次的过程。

这样可以严格证明复杂度是\(log\)的(可以理解为最多\(log\)次,就加到极限了)

int solve()
{
int now=0;
ll uu=0;
while(now!=n)
{
int nxt = getpos(1,1,n,2*uu);
//if (query(1,1,n,nxt-1)*2==query(1,1,n,nxt)) return nxt;
if(kachang == 2*a[nxt]) return nxt;
now=nxt;
uu=kachang;
}
return -1;
}

计算第一个大于等于某个数的过程,我们可以直接选择再线段树上二分,这样复杂度是\(log\)的,如果要是不在线段树上二分,可能需要两个\(log\)的时间

int getpos(int root,int l,int r,ll lim)
{
if (l==r)
{
kachang = f[root];
return l;
}
pushdown(root,l,r);
int mid = l+r >> 1;
if (f[root<<1]>=lim) return getpos(root<<1,l,mid,lim);
else return getpos(root<<1|1,mid+1,r,lim);
}

(而且这个题会卡常,我这里贴的代码都是卡常之后的,可能比较难理解)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 4e5+1e2;
ll f[4*maxn];
ll add[4*maxn];
int n,m;
int pos,ans;
ll sum[maxn],a[maxn];
void up(int root)
{
f[root]=max(f[root<<1],f[root<<1|1]);
}
void pushdown(int root,int l,int r)
{
if (add[root])
{
add[root<<1]+=add[root];
add[root<<1|1]+=add[root];
f[root<<1]+=add[root];
f[root<<1|1]+=add[root];
add[root]=0;
}
}
void build(int root,int l,int r)
{
if (l==r)
{
f[root]=sum[l];
return;
}
int mid = l+r >> 1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
up(root);
}
void update(int root,int l,int r,int x,int y,ll p)
{
if (x<=l && r<=y)
{
f[root]+=p;
add[root]+=p;
return;
}
pushdown(root,l,r);
int mid = l+r >> 1;
if (x<=mid) update(root<<1,l,mid,x,y,p);
if (y>mid) update(root<<1|1,mid+1,r,x,y,p);
up(root);
}
ll query(int root,int l,int r,int x)
{
if (x==0) return 0;
if (l==r)
{
return f[root];
}
pushdown(root,l,r);
int mid = l+r >> 1;
ll ans = -1e18;
if (x<=mid) ans=max(ans,query(root<<1,l,mid,x));
if (x>mid) ans=max(ans,query(root<<1|1,mid+1,r,x));
return ans;
}
long long kachang;
int getpos(int root,int l,int r,ll lim)
{
if (l==r)
{
kachang = f[root];
return l;
}
pushdown(root,l,r);
int mid = l+r >> 1;
if (f[root<<1]>=lim) return getpos(root<<1,l,mid,lim);
else return getpos(root<<1|1,mid+1,r,lim);
}
int solve()
{
int now=0;
ll uu=0;
while(now!=n)
{
int nxt = getpos(1,1,n,2*uu);
//if (query(1,1,n,nxt-1)*2==query(1,1,n,nxt)) return nxt;
if(kachang == 2*a[nxt]) return nxt;
now=nxt;
uu=kachang;
}
return -1;
}
signed main()
{
n=read();m=read();
for (register int i=1;i<=n;++i) a[i]=read();
for (register int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i];
build(1,1,n);
for (register int i=1;i<=m;++i)
{
int x=read(),y=read();
update(1,1,n,x,n,y-a[x]);
a[x]=y;
cout<<solve()<<"\n";
}
return 0;
}

CF992E Nastya and King-Shamans(线段树二分+思维)的更多相关文章

  1. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  2. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  3. hdu4614 线段树+二分 插花

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  4. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  5. luogu4422 [COCI2017-2018#1] Deda[线段树二分]

    讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...

  6. bzoj4399 魔法少女LJJ 线段树合并+线段树二分+并查集

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4399 题解 毒瘤题 \(9\) 种操作还有支持动态图的连通性 仔细读题 $ c<=7$. ...

  7. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  8. Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

    题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l, ...

  9. 洛谷$P2824\ [HEOI2016/TJOI2016]$ 排序 线段树+二分

    正解:线段树+二分 解题报告: 传送门$QwQ$ 昂着题好神噢我$jio$得$QwQQQQQ$,,, 开始看到长得很像之前考试题的亚子,,,然后仔细康康发现不一样昂$kk$,就这里范围是$[1,n]$ ...

随机推荐

  1. redis BLPOP命令阻塞,非阻塞(读了好久才懂)

    来源于:http://redisdoc.com/list/blpop.html#id1BLPOP key [key -] timeout 可用版本: >= 2.0.0 时间复杂度: O(1) B ...

  2. springboot邮通知553错误和

    com.sun.mail.smtp.SMTPSendFailedException: 553 Mail from must equal authorized user ; nested excepti ...

  3. 在Excel中怎样才能在某一行前面一次插入多行?

    你在要插入的行以下选中多少行,点插入,就能插入多少行. ​

  4. Charles-抓取https请求

    在未经设置之前,Charles是无法抓取https请求的,会出现unknown的标识.我们可以通过以下两步设置,解决该问题. 第一步:安装证书 https是在http的基础上加入ssl层,通过ssl来 ...

  5. 你的 SQL 还在回表查询吗?快给它安排覆盖索引

    什么是回表查询 小伙伴们可以先看这篇文章了解下什么是聚集索引和辅助索引:Are You OK?主键.聚集索引.辅助索引,简单回顾下,聚集索引的叶子节点包含完整的行数据,而非聚集索引的叶子节点存储的是每 ...

  6. Java实现一个死锁

    Java实现一个死锁 有一个藏宝图(treasureMapFragment)分成两份jack持有treasureMapFragment1残片1,json持有残片2.jack要求必须先看到json的残图 ...

  7. Pytest系列(12)- 测试结果生成HTML报告插件之pytest-html的详细使用

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 环境前提 Python3.6+ 安 ...

  8. python3 爬虫五大模块之一:爬虫调度器

    Python的爬虫框架主要可以分为以下五个部分: 爬虫调度器:用于各个模块之间的通信,可以理解为爬虫的入口与核心(main函数),爬虫的执行策略在此模块进行定义: URL管理器:负责URL的管理,包括 ...

  9. es查询--请求body

    查询的JSON结构 普通查询 { "query": { # 查询条件 "match_all": {} //匹配所有文档, 所有 _score 为1.0 # &q ...

  10. Vue3.x全家桶+vite+TS-构建Vue3基本框架

    目录 一.搭建基础项目 1.vite创建项目 3.运行项目 2.环境变量设置介绍 vite配置多环境打包 二.配置Router 1.安装路由 2.配置路由 3.引入 三.配置Vuex 1.安装vuex ...