Contest Hunter 模拟赛09 A [线段树维护斜率]
题面
思路
首先看看我们到底要干什么:有$1e6$次询问,遍历$i$,每次要求一个形如$b_i \ast a_j - a_i \ast b_j$的东西的最大值
考虑如果一个$j$的决策在当前的$i$上比$k$这个位置更优会得到什么:
$b_i \ast a_j - a_i \ast b_j > b_i \ast a_k - a_i \ast b_k$
$b_i \ast (a_j-a_k) > a_i \ast (b_j-b_k)$
$\frac{b_i}{a_i} > \frac{b_j-b_k}{a_j-a_k}$
考虑对于询问区间维护右边那个玩意儿的下凸包$lis$,显然第一个满足$\frac{b_{lis[j]}-b_{lis[j+1]}}{a_{lis[j]}-a_{lis[j+1]}} > \frac{b_i}{a_i}$的$j$就是最优解,因为维护了下凸包所以这个东西可以二分
我们开一棵线段树维护每个线段树节点区间上的下凸包,查询的时候就把目标区间拆分到线段树节点上,再做一次上面的操作
线段树维护凸包的总复杂度是$O(q\log n)$,查询因为区间拆分完了二分,复杂度还是$O(q\log n)$
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#define MOD 1000000007
#define ll long long
using namespace std;
inline ll read(){
ll re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n;ll g[1000010];int a[1000010],b[1000010],c[1000010];
int mmp[30000010],len[4000010];
int *q[4000010],*cur=mmp;//动态内存池,实际上大概2.5e7就够了
void build(int l,int r,int num){
q[num]=cur;len[num]=0;
cur+=r-l+2;
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,num<<1);
build(mid+1,r,num<<1|1);
}
inline double get(int l,int r){return (double)(b[r]-b[l])/(double)(a[r]-a[l]);}
void change(int l,int r,int num,int pos){插入新元素,维护log个凸包
while(len[num]>=2&&get(q[num][len[num]-1],q[num][len[num]])>get(q[num][len[num]],pos)) q[num][len[num]--]=0;
q[num][++len[num]]=pos;
if(l==r) return;
int mid=(l+r)>>1;
if(mid>=pos) change(l,mid,num<<1,pos);
else change(mid+1,r,num<<1|1,pos);
}
inline ll f(int i,int j){
return 1ll*b[i]*a[j]-1ll*b[j]*a[i];
}
ll query(int l,int r,int ql,int qr,int num,double lim,int now){
if(l>=ql&&r<=qr){//找到目标拆分区间,二分查询
if(len[num]==1) return f(now,q[num][1]);//注意特判凸包只有一个点的情况
l=1;r=len[num]-1;int mid;
while(l<r){
mid=(l+r)>>1;
if(get(q[num][mid],q[num][mid+1])<lim) l=mid+1;
else r=mid;
}
if(l==len[num]-1&&get(q[num][l],q[num][l+1])<lim) l++;//注意特判找到的倒数第二个点没有最后一个点优的情况
return f(now,q[num][l]);
}
int mid=(l+r)>>1;ll re=-1e18;
if(mid>=ql) re=max(re,query(l,mid,ql,qr,num<<1,lim,now));
if(mid<qr) re=max(re,query(mid+1,r,ql,qr,num<<1|1,lim,now));
return re;
}
int main(){
n=read();int i;ll tmp;
for(i=1;i<=n;i++) a[i]=read();
for(i=1;i<=n;i++) b[i]=read();
for(i=1;i<=n;i++) c[i]=read();
build(1,n,1);
for(i=1;i<=n;i++){
a[i]^=g[i-1];
b[i]^=g[i-1];
c[i]^=g[i-1];
change(1,n,1,i);
g[i]=(g[i-1]+(tmp=query(1,n,1,i-c[i],1,(double)b[i]/(double)a[i],i))%MOD+MOD)%MOD;
}
cout<<g[n]<<'\n';
}
Contest Hunter 模拟赛09 A [线段树维护斜率]的更多相关文章
- Contest Hunter 模拟赛09 C [树形dp+差分]
题面 传送门 思路 又双叒叕是一道差分题我没想出来......记录一下 首先这个"所有祖先都比自己小"等价于"父亲比自己小" 这题的基础dp方程很显然,$dp[ ...
- Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...
- [CSP-S模拟测试]:椎(线段树维护区间最值和单调栈)
题目描述 虽不能至,心向往之. $Treap=Tree+Heap$ 椎$=$树$+$堆 小$\pi$学习了计算机科学中的数据结构$Treap$. 小$\pi$知道$Treap$指的是一种树. 小$\p ...
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点
容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...
- 【10.6校内测试】【小模拟】【hash+线段树维护覆盖序列】
一开始看到题就果断跳到T2了!!没想到T2才是个大坑,浪费了两个小时QAQ!! 就是一道小模拟,它怎么说就怎么走就好了! 为什么要用这么多感叹号!!因为统计答案要边走边统计!!如果每个数据都扫一遍20 ...
- The 2019 Asia Nanchang First Round Online Programming Contest C(cf原题,线段树维护矩阵)
题:https://nanti.jisuanke.com/t/41350 分析:先将字符串转置过来 状态转移,因为只有5个状态,所以 i 状态到 j 状态的最小代价就枚举[i][k]->[k][ ...
- 7.18 NOI模拟赛 因懒无名 线段树分治 线段树维护直径
LINK:因懒无名 20分显然有\(n\cdot q\)的暴力. 还有20分 每次只询问一种颜色的直径不过带修改. 容易想到利用线段树维护直径就可以解决了. 当然也可以进行线段树分治 每种颜色存一下直 ...
随机推荐
- ruby OpenURI模块使用
OpenURI is an easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP(OpenURI支持重定向) 像打开普通文件那样打开ht ...
- JavaSE基础复习---1---2018/9/27
2018/9/27 JavaSE学习笔记-1 目录: Java的起源 Java语言概述 1.Java的起源 现代编程语言的发展,大致可以理解为,机器码语言---汇编语言---C语言---C++语言-- ...
- VHDL入门学习-程序组成
1. VHDL程序的组成 一个完整的VHDL程序是以下五部分组成的: 2. 库(LIBRARY):比较好理解,调用系统已有的库,WORK库就是用户当前编辑文件所在的文件夹, IEEE库:由IEEE(美 ...
- HTML 特效标签
HTMl 文字移动<MARQUEE scrollAmount=2 scrollDelay=150 direction=up height=120> 内容 </marquee>s ...
- hibernate 各历史版本下载 spring各历史版本下载
hibernate 各历史版本下载http://sourceforge.net/projects/hibernate/files/ spring各历史版本下载http://www.springsour ...
- centos7下安装oracle11gR2的详细步骤
环境准备 安装包: CentOS-7-x86_64-DVD linux.x64_11gR2_database_1of2.zip linux.x64_11gR2_database_2of2.zip 本教 ...
- IDEA的terminal设置成Linux的终端一样
方式一:通过在Windows上安装Linux命令行工具 前提:需要安装Linux终端的命令行工具,并且最好可以安装 Gow (一个Windows下模拟Linux命令行工具集合,它集成了 Liunx 环 ...
- (原)UnrealObj篇 : 反射获取Struct类型
@Author: 白袍小道 转载请说明 案例一:蓝图传递任意Struct ,导出struct的相关属性 相关: 1.宏:DECLARE_FUNCTION: 此宏用于在自动生成的样板代码中声明t ...
- 问题 B: Prime Number
题目描述 Output the k-th prime number. 输入 k≤10000 输出 The k-th prime number. 样例输入 10 50 样例输出 29 229 #incl ...
- 使用JDK的keytool生成Android签名证书
生成证书:keytool -genkey -alias [yourapp] -keyalg RSA -validity 20000 -keystore [yourapp].keystore 输入key ...