题面

传送门

思路

首先看看我们到底要干什么:有$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 [线段树维护斜率]的更多相关文章

  1. Contest Hunter 模拟赛09 C [树形dp+差分]

    题面 传送门 思路 又双叒叕是一道差分题我没想出来......记录一下 首先这个"所有祖先都比自己小"等价于"父亲比自己小" 这题的基础dp方程很显然,$dp[ ...

  2. 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 ...

  3. [CSP-S模拟测试]:椎(线段树维护区间最值和单调栈)

    题目描述 虽不能至,心向往之. $Treap=Tree+Heap$ 椎$=$树$+$堆 小$\pi$学习了计算机科学中的数据结构$Treap$. 小$\pi$知道$Treap$指的是一种树. 小$\p ...

  4. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  5. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  6. 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点

    容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...

  7. 【10.6校内测试】【小模拟】【hash+线段树维护覆盖序列】

    一开始看到题就果断跳到T2了!!没想到T2才是个大坑,浪费了两个小时QAQ!! 就是一道小模拟,它怎么说就怎么走就好了! 为什么要用这么多感叹号!!因为统计答案要边走边统计!!如果每个数据都扫一遍20 ...

  8. The 2019 Asia Nanchang First Round Online Programming Contest C(cf原题,线段树维护矩阵)

    题:https://nanti.jisuanke.com/t/41350 分析:先将字符串转置过来 状态转移,因为只有5个状态,所以 i 状态到 j 状态的最小代价就枚举[i][k]->[k][ ...

  9. 7.18 NOI模拟赛 因懒无名 线段树分治 线段树维护直径

    LINK:因懒无名 20分显然有\(n\cdot q\)的暴力. 还有20分 每次只询问一种颜色的直径不过带修改. 容易想到利用线段树维护直径就可以解决了. 当然也可以进行线段树分治 每种颜色存一下直 ...

随机推荐

  1. php-5.6.26源代码 - hash存储结构 - 添加

    添加 , (void *)module, sizeof(zend_module_entry), (void**)&module_ptr){ // zend_hash_add 定义在文件“php ...

  2. python多线程举例

    Python中使用线程有两种方式:函数或者用类来包装线程对象. 1.  函数式:调用thread模块中的start_new_thread()函数来产生新线程.如下例: import time      ...

  3. 服务器空间不足导致mysql服务器无法运行

    今天有朋友请我帮忙解决一个问题,他公司服务器mysql数据库一直连接失败.登录服务期之后发现服务器空间占满了,导致mysql不能启动. 下面说解决方法: 首先查看空间占用,发现空间占满了 df -h ...

  4. Yii2.0 游客访问限制(转)

    最近在用Yii2.0做项目,其中需要实现一个功能:没有登录不能访问部分页面,即游客身份访问限制.查了半天资料,终于找到答案.解决方法如下: 在access里,access即访问的意思,其中有个配置项 ...

  5. php file_exists中文路径不存在问题

    php的file_exists函数使用中文路径,会显示文件不存在,即使文件已经存在了也会报这个错. 解决方法: <?php $file_name='D://360极速浏览器下载//a.txt'; ...

  6. [转]Makefile中使用$$的使用

    在makefile中,会经常使用shell命令,也经常见到$var 和 $$var的情况,有什么区别呢,区别大了.不要认为在makefile的规则的命令行中使用$var就是将makefile的变量和s ...

  7. HDU暑假多校第六场K-werewolf

    一.题意 好人必然说真话,坏人不一定说真话,给定N个人的言论<每人一个发言.不谈及自己>,要求指出有多少个人一定是好人,有多少个人一定是坏人.#define 狼人 坏人#define 村民 ...

  8. 当app出现线上奔溃,该如何办?

    1.如何追踪app崩溃率,如何解决线上闪退 当iOS设备上的App应用闪退时,操作系统会生成一个crash日志,保存在设备上.crash日志上有很多有用的信息,比如每个正在执行线程的完整堆栈跟踪信息和 ...

  9. java集合浅谈(一)

    一.类库结构图概览 容器对象仅能持有对象引用(对象的指针),而不是Copy对象信息,从网上搜得几张Java中集合类库的结构图,如下所示: 二.解说Collection 2.1 Collection ( ...

  10. 接口测试工具postman(四)导入导出文件

    1.导入json文件 2.单个文件夹导出,文件格式是 json文件 3.所有数据导出,文件格式是 json文件