本文将同步发布于:

题目

题目链接:洛谷 P7028gym101612J

题意概述

有一个长度为 \(n\) 的数列,第 \(i\) 个元素的值为 \(a_i\),其中 \(a_i\neq 0\),定义 \(P\) 为数列中所有正整数的和,\(N\) 为所有负整数的和。定义一个元素的重要值 \(w_i=\begin{cases}\dfrac{a_i}{P}&a_i>0\\
\dfrac{a_i}{|N|}&\text{otherwise}\end{cases}\)

,并定义 \(s_i\) 为前 \(i\) 个元素的重要值之和,即 \(\sum\limits_{j=1}^iw_j\)。

请先求出当前数列中使 \(s_i\) 最小的 \(i\)。然后有 \(m\) 次操作,每次操作将某个元素改成一个给定的值,请在每次操作后求出当数列中使 \(s_i\) 最大最小下标 \(i\)。

题解

分析性质

事实上,我们要求的就是最小的 \(i\) 使得

\[s_i=\max_{j=1}^n\{s_j\}
\]

考虑到 \(P\) 和 \(|N|\) 均为正整数(若有一项是 \(0\),则显然答案为 \(n\)),我们给等式两边同时乘上 \(P\cdot |N|\),得到

\[s_i\cdot P\cdot |N|=\max_{j=1}^n\left\{s_j\cdot P\cdot |N|\right\}
\]

拆开 \(s_i\) 的定义式,得到

\[\sum_{k=1}^iw_k\cdot P\cdot |N|=\max_{j=1}^n\left\{\sum_{k=1}^jw_k\cdot P\cdot |N|\right\}
\]

再代入 \(w_i\) 的定义式,得到单个点的值为

\[\begin{aligned}
&\sum_{k=1}^i\left(\frac{a_k[a_k<0]}{|N|}P|N|+\frac{a_k[a_k>0]}{P}P|N|\right)\\
=&\sum_{k=1}^i\left(a_k[a_k<0]\cdot P+a_k[a_k>0]\cdot |N|\right)\\
=&\sum_{k=1}^i\left(a_k[a_k<0]\cdot P+a_k[a_k>0]\cdot |N|\right)\\
=&\left(\sum_{a_k<0,k\leq i}^ia_k\right)\cdot P+\left(\sum_{a_k>0,k\leq i}a_k\right)\cdot|N|\\
=&-\left(\sum_{a_k<0,k\leq i}^i-a_k\right)\cdot P+\left(\sum_{a_k>0,k\leq i}a_k\right)\cdot |N|\\
=&\left(\sum_{a_k>0,k\leq i}a_k\right)\cdot |N|-\left(\sum_{a_k<0,k\leq i}^i-a_k\right)\cdot P
\end{aligned}
\]

图形转换

我们观察上式,不难发现它与叉积的形式类似。

我们不妨定义

\[\vec{p}_i=
\begin{cases}
(a_i,0),&a_i>0\\
(0,-a_i),&a_i<0
\end{cases}
\]

再定义 \(\overrightarrow{\texttt{sum}}_i=\sum\limits_{j=1}^i\vec{p}_j\)

那么

\[\left(\sum_{a_k>0,k\leq i}a_k\right)\cdot |N|-\left(\sum_{a_k<0,k\leq i}^i-a_k\right)\cdot P
\]

就可以转化为

\[\overrightarrow{\texttt{sum}}_i\times \overrightarrow{\texttt{sum}}_n
\]

现在问题转化为了给定一个向量 \(\overrightarrow{\texttt{sum}}_n\) 和一堆向量 \(\overrightarrow{\texttt{sum}}_i\),求解其叉积的最大值。

我们不难得到,叉积的最大值一定在 \(\overrightarrow{\texttt{sum}}_i\) 对应的下凸包上取到。

分析时间复杂度

现在我们需要维护一个下凸包,每次询问在凸包上二分得到答案,而每次修改我们需要暴力重构凸包。

  • 询问:时间复杂度为 \(\Theta(\log_2n)\);
  • 修改:由于这些点的横纵坐标都具有单调性,无需排序,时间复杂度为 \(\Theta(n)\)。

两种操作的时间复杂度不均衡,而操作次数却相同,这提示我们用 序列分块 的方法均衡时间复杂度。

序列分块

考虑对每 \(B\) 个操作分一块,每个操作只考虑自己 块内的所有向量。

根据叉积分配率 \(\bold{a}\times(\bold{b}+\bold{c})=\bold{a}\times\bold{b}+\bold{a}\times\bold{c}\),我们不难得出,这样在每个块内部查询到的最大值一定是块的局部最大值。

  • 修改:我们每次修改都暴力重构一个块内部的下凸包,并维护前缀和,时间复杂度 \(\Theta(B+\log_2n)\);
  • 查询:我们每次查询都询问所有块的局部最大值,再通过快速查询前缀和(树状数组)得到真实最大值,时间复杂度 \(\Theta(\frac{q}{B}\log_2B+\frac{q}{B}\log_2n)\)。

理论分析得到 \(B=\sqrt{n\log_2n}\) 时复杂度最优(为了方便,视 \(\log_2B\) 与 \(\log_2n\) 同阶,\(n\) 与 \(q\) 同阶),为 \(\Theta(n\sqrt{n\log_2n})\)。

参考程序

#include<bits/stdc++.h>
using namespace std;
#define reg register
typedef long long ll;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
static char buf[1<<21],*p1=buf,*p2=buf;
#define flush() (fwrite(wbuf,1,wp1,stdout),wp1=0)
#define putchar(c) (wp1==wp2&&(flush(),0),wbuf[wp1++]=c)
static char wbuf[1<<21];int wp1;const int wp2=1<<21;
inline int read(void){
reg bool f=false;
reg char ch=getchar();
reg int res=0;
while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
while(isdigit(ch))res=10*res+(ch^'0'),ch=getchar();
return f?-res:res;
} inline void writeln(reg int x){
static char buf[32];
reg int p=-1;
if(!x) putchar('0');
else while(x) buf[++p]=(x%10)^'0',x/=10;
while(~p) putchar(buf[p--]);
putchar('\n');
return;
} struct Vector{
int x,y;
inline Vector(reg int x=0,reg int y=0):x(x),y(y){
return;
}
inline Vector operator+(const Vector& a)const{
return Vector(x+a.x,y+a.y);
}
inline Vector operator-(const Vector& a)const{
return Vector(x-a.x,y-a.y);
}
inline Vector operator-(void)const{
return Vector(-x,-y);
}
}; inline ll dot(const Vector& a,const Vector& b){
return 1ll*a.x*b.x+1ll*a.y*b.y;
} inline ll cross(const Vector& a,const Vector& b){
return 1ll*a.x*b.y-1ll*a.y*b.x;
} typedef Vector Point; const int MAXN=5e4+5;
const int MAXM=5e4+5;
const ll inf=0x3f3f3f3f3f3f3f3f; int n,m;
int a[MAXN];
int lef[MAXN],rig[MAXN],id[MAXN]; struct Node{
int id;
Point p;
inline Node(reg int id,const Point& p):id(id),p(p){
return;
}
}; vector<Node> S[MAXN]; inline void build(reg int id){
S[id].clear();
Point sum(0,0);
for(reg int i=lef[id];i<=rig[id];++i){
if(a[i]>0)
sum=sum+Point(a[i],0);
else
sum=sum+Point(0,-a[i]);
while(S[id].size()>=2u&&cross(S[id].back().p-(S[id].end()-2)->p,sum-S[id].back().p)<0)
S[id].pop_back();
S[id].push_back(Node(i,sum));
}
return;
} inline int query(reg int id,const Vector& p){
reg int _l=0,_r=S[id].size()-1,_mid;
while(_l<_r){
_mid=(_l+_r)>>1;
if(cross(S[id][_mid+1].p-S[id][_mid].p,p)>0)
_l=_mid+1;
else
_r=_mid;
}
return S[id][_l].id;
} namespace BIT{
inline int lowbit(reg int x){
return x&(-x);
}
int n;
Vector unit[MAXN];
inline void Init(reg int s){
n=s;
return;
}
inline void update(reg int id,const Vector& a){
for(reg int i=id;i<=n;i+=lowbit(i))
unit[i]=unit[i]+a;
return;
}
inline Vector query(reg int id){
Vector res;
for(reg int i=id;i;i^=lowbit(i))
res=res+unit[i];
return res;
}
} int main(void){
n=read(),m=read();
for(reg int i=1;i<=n;++i)
a[i]=read();
BIT::Init(n);
for(reg int i=1;i<=n;++i)
if(a[i]>0)
BIT::update(i,Vector(a[i],0));
else
BIT::update(i,Vector(0,-a[i]));
reg int B=max(100,int(sqrt(n*log2(n)))),tot=(n+B-1)/B;
pair<ll,int> ans=make_pair(inf,-1);
for(reg int i=1;i<=tot;++i){
lef[i]=(i-1)*B+1,rig[i]=min(i*B,n);
for(reg int j=lef[i];j<=rig[i];++j)
id[j]=i;
build(i);
Vector sum=BIT::query(n);
int pos=query(i,sum);
ans=min(ans,make_pair(-cross(BIT::query(pos),sum),pos));
}
writeln(ans.second);
while(m--){
static int p,v;
p=read(),v=read();
if(a[p]>0)
BIT::update(p,-Vector(a[p],0));
else
BIT::update(p,-Vector(0,-a[p]));
a[p]=v;
if(a[p]>0)
BIT::update(p,Vector(a[p],0));
else
BIT::update(p,Vector(0,-a[p]));
build(id[p]);
ans=make_pair(inf,-1);
Vector sum=BIT::query(n);
for(reg int i=1;i<=tot;++i){
int pos=query(i,sum);
ans=min(ans,make_pair(-cross(BIT::query(pos),sum),pos));
}
writeln(ans.second);
}
flush();
return 0;
}

「题解」NWRRC2017 Joker的更多相关文章

  1. 「题解」NWRRC2017 Grand Test

    本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷 P7025.gym101612G. 题意概述 给你一张有 \(n\) 个点 \(m\) 条边的无向图,无重边无自环, ...

  2. 「题解」「美团 CodeM 资格赛」跳格子

    目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...

  3. 「题解」「HNOI2013」切糕

    文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...

  4. 「题解」JOIOI 王国

    「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...

  5. 「题解」:[loj2763][JOI2013]现代豪宅

    问题 A: 现代豪宅 时间限制: 1 Sec  内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...

  6. 「题解」:$Six$

    问题 A: Six 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...

  7. 「题解」:$Smooth$

    问题 A: Smooth 时间限制: 1 Sec  内存限制: 512 MB 题面 题面谢绝公开. 题解 维护一个队列,开15个指针,对应前15个素数. 对于每一次添加数字,暴扫15个指针,将指针对应 ...

  8. 「题解」:Kill

    问题 A: Kill 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...

  9. 「题解」:y

    问题 B: y 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...

随机推荐

  1. [转载] 关于Win7 x64下过TP保护的一些思路,内核层过保护,驱动过保护

    首先特别感谢梦老大,本人一直没搞懂异常处理机制,看了他的教程之后终于明白了.在他的教程里我学到了不少东西.第一次在论坛发帖,就说说Win7 x64位下怎么过TP保护.如果有讲错的地方,还望指出.说不定 ...

  2. pr中打开Audition编辑剪辑?

    前景 现在一般的adobe全家桶都是一键安装破解. 天翼网盘链接,下载不限速,没有账号就现注册一个即可. https://cloud.189.cn/t/UZRjuqAZ3E7r (访问码:8ago) ...

  3. SSM项目使用Spring提供的测试

    在测试类上添加注解@RunWith(SpringJUnit4ClassRunner.class)和@ContextConfiguration(locations = {"classpath: ...

  4. 【实用小技巧】spring springmvc集成shiro时报 No bean named 'shiroFilter' available

    查了网上的,很多情况,不同的解决办法,总归一点就是配置文件加载的问题. 先看下配置文件中的配置 web.xml中的主要配置(这是修改后不在报错的:仅仅修改了一个位置:[classpath:spring ...

  5. GO反射类实例

    变量的内在机制 类型信息:是静态的元信息,是预先定义好的 值信息:是程序运行过程中动态改变的 反射的使用 获取类型信息:reflect.TypeOf,是静态的 获取值信息:reflect.ValueO ...

  6. 攻防世界(十二)upload1

    攻防世界系列 :upload1 1.打开题目,文件上传. 2.立即上传shell 1.php <?php @eval($_POST[root]); ?> 提示只能上传图片 3.burp改报 ...

  7. Centos7如何安装开源办公软件Libreoffice

    在Centos7安装了WPS,但是用了没两月就出问题,无法正常使用.(准确来说,安装的WPS一直都有各种问题存在,但是没有影响到主要功能也就将就着用,后来是直接输入不了文字) 既然是开源系统,自然而然 ...

  8. "sar"工具 利用率

    LTP--linux稳定性测试 linux性能测试 ltp压力测试   余二五 2017-11-14 16:20:00 浏览1172 linux 日志 配置 内存管理 测试 脚本 性能测试 压力测试 ...

  9. 057.Python前端Django模型ORM多表查询

    一 基于对象的查询 1.1 一对多查询 设计路由 from django.contrib import admin from django.urls import path from app01 im ...

  10. 009.kubernets的调度系统之污点和容忍

    Taints和Tolerations(污点和容忍) Taint需要与Toleration配合使用,让pod避开那些不合适的node.在node上设置一个或多个Taint后,除非pod明确声明能够容忍这 ...