本文将同步发布于:

题目

题目链接:洛谷 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. Win64 驱动内核编程-21.DKOM隐藏和保护进程

    DKOM隐藏和保护进程 主要就是操作链表,以及修改节点内容. DKOM 隐藏进程和保护进程的本质是操作 EPROCESS 结构体,不同的系统用的时候注意查下相关定义,确定下偏移,下面的数据是以win7 ...

  2. Day002 Java开发环境搭建

    Java开发环境搭建 JDK.JRE.JVM JDK: Java Development Kit(包涵JRE) JRE: Java Runtime Environment(包涵JVM) JVM: Ja ...

  3. JVM核心技术(第一篇)

    目录 Java基础知识 一. 字节码技术 二.JVM类加载器 类的加载时机 三.JVM内存结构 四.JVM启动参数 4.1 系统属性参数 4.2 运行模式 4.3 堆内存 4.4 GC相关 4.5 分 ...

  4. 测试中常用的链接URL----方便自己查找

    1.TesterHome:https://testerhome.com/ 2.selenium的操作手册:https://selenium-python.readthedocs.io/ 3.

  5. qsort和sort学习与比较

    阅读另一篇博文Uva 642 - Word Amalgamation sort qsort 1.qsort函数: 原 型: void qsort(void *base, int nelem, int ...

  6. 【建议收藏】缺少 Vue3 和 Spring Boot 的实战项目经验?我这儿有啊!

    缺少 Vue3 和 Spring Boot 的实战项目经验?缺少学习项目和练手项目?我这儿有啊! 从 2019 年到 2021 年,空闲时间里陆陆续续做了一些开源项目,推荐给大家啊!记得点赞和收藏噢! ...

  7. 最全的cURL命令使用

    cURL是什么 curl是Linux命令行工具,可以使用任何可支持的协议(如HTTP.FTP.IMAP.POP3.SCP.SFTP.SMTP.TFTP.TELNET.LDAP或FILE)在服务器之间传 ...

  8. kubernetes dashboard延长自动超时注销

    方法1:部署清单时,修改yaml文件,添加 container.Args 增加 --token-ttl=43200 其中43200是设置自动超时的秒数.也可以设置 token-ttl=0 以完全禁用超 ...

  9. 使用alpine为基础镜像Q&A

    作为go应用存在二进制文件却不能执行 明明镜像中有对应的二进制文件,但是执行时却提示 not found 或 no such file 或 standard_init_linux.go:211: ex ...

  10. [其他] vscode 快速教程

    概述 vs:集成开发环境,包括软件生命周期中需要的大部分工具,如UML,代码管控,IDE等 vs code:代码编辑器,支持插件扩展,对网页和云端开发做了优化 快捷键 F1/ctrl+shift+p: ...