这是一道卡常好题

从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. vue3.0入门(一)

    前言 最近在b站上学习了飞哥的vue教程 学习案例已上传,下载地址 使用方式 使用在线cdn 下载js文件并自托管,引入到项目后使用 使用npm安装后,用cli来构建项目 声明式渲染 Vue2需引入v ...

  2. 那些优秀的python代码

    时间:2019-04-18 收藏:PangYuaner 标题:Python如何生成树形图案 地址:https://www.jb51.net/article/132049.htm 标题:用python- ...

  3. GetX代码生成IDEA插件,超详细功能讲解(透过现象看本质)

    前言 本文章不是写getx框架的使用,而且其代码生成IDEA插件的功能讲解 我之前写过俩篇很长很长的getx文章 一篇入门使用:Flutter GetX使用---简洁的魅力! 一篇原理深度剖析:Flu ...

  4. 编程读写CAD文件验证

    背景 B/S应用系统,根据用户上传数据:业务数据和CAD坐标数据,经过一系列运筹算法运算后,输出一批坐标数据,作为给用户的规划结果.此时需要方便直观的给用户展示坐标数据.可选方式有两个: web页面画 ...

  5. IOS 集成 Bilibili IJKPlayer播放器,播放rtmp视频流

    因为公司项目需要,我一个连iPhone都没用过的人竟然跑去开发iOS APP.近一段时间一直忙于赶项目,到今天差不多了,所以记录一下当时遇到的各种坑,先从ios 集成 ijkplayer播放器说起! ...

  6. AI异构通信:重压下的突围,华为P50系列的卓越体验

    撰文 |懂懂 编辑 | 秦言 来源:懂懂笔记 "华为不会让消费者失望."华为消费者业务CEO余承东在P50系列发布会上如是说. 今年4月美国对华为第四轮制裁以来,华为终端产品无缘5 ...

  7. rune和byte在处理字符/字符串中的应用.

    rune和byte在处理字符/字符串中的应用. 定义: rune是int32的别名,-2147483648->2147483647,常用来表示UNICODE字符集,可以用来处理包含中文/非中文的 ...

  8. Devexpress 饼状图

    <dxc:ChartControl Name="chart"                                BorderThickness="0&q ...

  9. 1 行Python代码能干哪些事,这 13个你知道吗?

    首先你要了解一下Python之禅,一行代码输出"The Zen of Python": python -c "import this"""& ...

  10. Java-枚举(Enum)

    1.枚举概述 枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常熟.当一个变量有几种固定可能的取值时,就可以将其定义为枚举类型. 1.1 声明枚举 Java中枚举是一个特殊的类,使用enum关 ...