「题解」NWRRC2017 Joker
本文将同步发布于:
题目
题目链接:洛谷 P7028、gym101612J。
题意概述
有一个长度为 \(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\) 使得
\]
考虑到 \(P\) 和 \(|N|\) 均为正整数(若有一项是 \(0\),则显然答案为 \(n\)),我们给等式两边同时乘上 \(P\cdot |N|\),得到
\]
拆开 \(s_i\) 的定义式,得到
\]
再代入 \(w_i\) 的定义式,得到单个点的值为
&\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}
\]
图形转换
我们观察上式,不难发现它与叉积的形式类似。
我们不妨定义
\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\)
那么
\]
就可以转化为
\]
现在问题转化为了给定一个向量 \(\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的更多相关文章
- 「题解」NWRRC2017 Grand Test
本文将同步发布于: 洛谷博客: csdn: 博客园: 简书. 题目 题目链接:洛谷 P7025.gym101612G. 题意概述 给你一张有 \(n\) 个点 \(m\) 条边的无向图,无重边无自环, ...
- 「题解」「美团 CodeM 资格赛」跳格子
目录 「题解」「美团 CodeM 资格赛」跳格子 题目描述 考场思路 思路分析及正解代码 「题解」「美团 CodeM 资格赛」跳格子 今天真的考自闭了... \(T1\) 花了 \(2h\) 都没有搞 ...
- 「题解」「HNOI2013」切糕
文章目录 「题解」「HNOI2013」切糕 题目描述 思路分析及代码 题目分析 题解及代码 「题解」「HNOI2013」切糕 题目描述 点这里 思路分析及代码 题目分析 这道题的题目可以说得上是史上最 ...
- 「题解」JOIOI 王国
「题解」JOIOI 王国 题目描述 考场思考 正解 题目描述 点这里 考场思考 因为时间不太够了,直接一上来就着手暴力.但是本人太菜,居然暴力爆 000 ,然后当场自闭- 一气之下,发现对 60pts ...
- 「题解」:[loj2763][JOI2013]现代豪宅
问题 A: 现代豪宅 时间限制: 1 Sec 内存限制: 256 MB 题面 题目描述 (题目译自 $JOI 2013 Final T3$「現代的な屋敷」) 你在某个很大的豪宅里迷路了.这个豪宅由东 ...
- 「题解」:$Six$
问题 A: Six 时间限制: 1 Sec 内存限制: 512 MB 题面 题面谢绝公开. 题解 来写一篇正经的题解. 每一个数对于答案的贡献与数本身无关,只与它包含了哪几个质因数有关. 所以考虑二 ...
- 「题解」:$Smooth$
问题 A: Smooth 时间限制: 1 Sec 内存限制: 512 MB 题面 题面谢绝公开. 题解 维护一个队列,开15个指针,对应前15个素数. 对于每一次添加数字,暴扫15个指针,将指针对应 ...
- 「题解」:Kill
问题 A: Kill 时间限制: 1 Sec 内存限制: 256 MB 题面 题面谢绝公开. 题解 80%算法 赛时并没有想到正解,而是选择了另一种正确性较对的贪心验证. 对于每一个怪,我们定义它的 ...
- 「题解」:y
问题 B: y 时间限制: 1 Sec 内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...
随机推荐
- Win64 驱动内核编程-21.DKOM隐藏和保护进程
DKOM隐藏和保护进程 主要就是操作链表,以及修改节点内容. DKOM 隐藏进程和保护进程的本质是操作 EPROCESS 结构体,不同的系统用的时候注意查下相关定义,确定下偏移,下面的数据是以win7 ...
- Day002 Java开发环境搭建
Java开发环境搭建 JDK.JRE.JVM JDK: Java Development Kit(包涵JRE) JRE: Java Runtime Environment(包涵JVM) JVM: Ja ...
- JVM核心技术(第一篇)
目录 Java基础知识 一. 字节码技术 二.JVM类加载器 类的加载时机 三.JVM内存结构 四.JVM启动参数 4.1 系统属性参数 4.2 运行模式 4.3 堆内存 4.4 GC相关 4.5 分 ...
- 测试中常用的链接URL----方便自己查找
1.TesterHome:https://testerhome.com/ 2.selenium的操作手册:https://selenium-python.readthedocs.io/ 3.
- qsort和sort学习与比较
阅读另一篇博文Uva 642 - Word Amalgamation sort qsort 1.qsort函数: 原 型: void qsort(void *base, int nelem, int ...
- 【建议收藏】缺少 Vue3 和 Spring Boot 的实战项目经验?我这儿有啊!
缺少 Vue3 和 Spring Boot 的实战项目经验?缺少学习项目和练手项目?我这儿有啊! 从 2019 年到 2021 年,空闲时间里陆陆续续做了一些开源项目,推荐给大家啊!记得点赞和收藏噢! ...
- 最全的cURL命令使用
cURL是什么 curl是Linux命令行工具,可以使用任何可支持的协议(如HTTP.FTP.IMAP.POP3.SCP.SFTP.SMTP.TFTP.TELNET.LDAP或FILE)在服务器之间传 ...
- kubernetes dashboard延长自动超时注销
方法1:部署清单时,修改yaml文件,添加 container.Args 增加 --token-ttl=43200 其中43200是设置自动超时的秒数.也可以设置 token-ttl=0 以完全禁用超 ...
- 使用alpine为基础镜像Q&A
作为go应用存在二进制文件却不能执行 明明镜像中有对应的二进制文件,但是执行时却提示 not found 或 no such file 或 standard_init_linux.go:211: ex ...
- [其他] vscode 快速教程
概述 vs:集成开发环境,包括软件生命周期中需要的大部分工具,如UML,代码管控,IDE等 vs code:代码编辑器,支持插件扩展,对网页和云端开发做了优化 快捷键 F1/ctrl+shift+p: ...