洛谷题目传送门

一血祭

向dllxl致敬!

算是YNOI中比较清新的吧,毕竟代码只有1.25k。

首先我们对着题意模拟,寻找一些思路。

每次选了一个最大的数后,它和它周围两个数都要减一。这样无论如何,我们都选不到旁边那两个数,只有第一次选的那个数会对答案产生它的大小的贡献。

于是就可以写出一个\(O(nm\log n)\)的暴力用来对拍了

#include<bits/stdc++.h>
#define LL long long
#define R register int
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
using namespace std;
const int SZ=1<<19,N=1e5+9;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
int a[N],b[N];
bool vis[N];
inline bool Cmp(R&x,R y){
return a[x]>a[y]||(a[x]==a[y]&&x<y);
}
int main(){
R n=in();
for(R i=1;i<=n;++i)a[i]=in();
for(R q=in();q--;){
a[in()]=in();
for(R i=1;i<=n;++i)b[i]=i;
sort(b+1,b+n+1,Cmp);
memset(vis+1,0,n);
LL ans=0;
for(R i=1;i<=n;++i){
if(vis[b[i]])continue;
vis[b[i]-1]=vis[b[i]]=vis[b[i]+1]=1;
ans+=a[b[i]];
}
printf("%lld\n",ans);
}
return 0;
}

进一步观察,对于一个序列中的一个极长单调区间,我们取到了最大的、第三大的、第五大的。。。

考虑用set维护好序列的所有极值点,相邻两个极值点所包含区间的贡献就可以通过树状数组查区间和直接算(注意分奇偶)。

单点修改的时候,只会影响到自己周围至多三个的极值点状态、以及左右各至多两个区间的单调性,暴力删掉原来的贡献再加新的贡献就好了。

统计答案时细节很多,边界问题也很多,想清楚后再动手还是很舒服的。

时间复杂度\(O((n+m)\log n)\),因为数据范围不怎么卡(这一点也是YNOI极罕见的)所以蒟蒻直接牺牲常数来减少代码长度了qaq

#include<bits/stdc++.h>
#define LL long long
#define I inline
#define R register int
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
using namespace std;
typedef set<int>::iterator IT;
const int SZ=1<<19,N=1e5+9;
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
G;while(*ip<'-')G;
R x=*ip&15;G;
while(*ip>'-'){x*=10;x+=*ip&15;G;}
return x;
}
int n,a[N];LL ans;set<int>s;
struct BIT{
LL a[N];
I void Upd(R i,R v){
for(;i<N;i+=i&-i)a[i]+=v;
}
I void Qry(R l,R r,LL v){
for(R i=r;i;i-=i&-i)v+=a[i];
for(R i=l;i;i-=i&-i)v-=a[i];
}
}b[2];
#define ODD(O) ((*l^*O(j=l))&1)
I void Calc(IT l,IT r,R op){
IT i,j;LL sum=*l&&a[*l+1]>a[*l]&&!ODD(--)&&!ODD(++)?a[*l]:0;
for(i=l++;i!=r;i=l++)
if(a[*l]>a[*i])b[*l&1].Qry(*i,*l,sum);
else b[*i&1].Qry(*i,*l-ODD(++),sum);
ans+=sum*op;
}
I void Chk(R x){
if((a[x]>a[x-1])!=(a[x+1]>a[x]))s.insert(x);
else s.erase(x);
}
I void Upd(R x){
R y=in();
IT i=s.lower_bound(x),l=i,r=i;
--l;if(l!=s.begin())--l;
++r;if(r==s.end()||(*i==x&&++r==s.end()))--r;
Calc(l,r,-1);
b[x&1].Upd(x,y-a[x]);a[x]=y;
Chk(x);if(x>1)Chk(x-1);if(x<n)Chk(x+1);
Calc(l,r,1);
}
int main(){
n=in();s.insert(0);s.insert(n+1);
for(R i=1;i<=n;++i)Upd(i);
for(R q=in();q;--q)Upd(in()),printf("%lld\n",ans);
return 0;
}

最新文章

  1. 通过HTML5的Drag and Drop生成拓扑图片Base64信息
  2. 解决webkit浏览器中js方法中使用window.event提示未定义的问题
  3. 2016ACM/ICPC亚洲区沈阳站-重现赛赛题
  4. 修改Oracle并行度的方法
  5. 更改linux文件夹的默认颜色
  6. 8种Nosql数据库系统对比
  7. 在Oracle里,表的别名不能用as,列的别名可以用as
  8. 在Oracle 11g r2中,EXP无法导出个别空的表
  9. 淺析LED、LED背光、OLED的技術原理與區別
  10. Linux之top
  11. Mysql条件的类型决定了是否能走索引
  12. 什么时候该选用Xamarin?
  13. 处女作《Web全栈开发进阶之路》出版了!
  14. ublox TMOD2
  15. SpringCloud Zuul网关的简单理解
  16. 两种 AuthorizationSchemes 在 ASP.NET Core 2
  17. JDBC概述
  18. 学习笔记之Linux / Shell / QSHELL
  19. C#异步编程のawait和async关键字来写异步程序
  20. 软件设计基础-C/S系统

热门文章

  1. 14-Requests+正则表达式爬取猫眼电影
  2. php开发之系统函数
  3. js判断一个对象{}是否为空对象,没有任何属性
  4. 数据处理 array json 格式 转换成 数组形式
  5. C++常用宏
  6. .Net批量插入数据
  7. Dart语法基础
  8. python之路--MySQL 库,表的详细操作
  9. 魔术方法之__call与__callStatic方法
  10. border-color的深入理解