题面

传送门

思路

首先看看我们到底要干什么:有$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. BC追踪

    项目又要开始改造了,记录一下改造过程中碰到的坑和解决思路,避免以后回头看看自己的笔记都不知道写了什么. (一)敏感信息混淆 (二)活用ComponentScan (三)Swagger配置多项目共用 ( ...

  2. Scala语法(二)

    (1)类,对象 //定义类(属性.方法),实例化对象 class counter{ *//主构造器 class counter(name:String,mode:Int){ ... } 实例化:val ...

  3. 生産管理(PP)

    伝票系 製造指図 マスタ系 生産資源/治工具 作業区 能力 作業手順 作業バージョン 作業記録 需要予測プロファイル 計画手配 MRP レシピ その他 カスタマイズ系 BOM関連 製造指図確認 伝票系 ...

  4. python2.7练习小例子(十二)

        12):题目:打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身.例如:153是一个"水仙花数" ...

  5. js获取浏览器内容宽高(小计)

    <SCRIPT LANGUAGE="JavaScript">var  s = "";s += "\r\n网页可见区域宽:"+ d ...

  6. python的正则表达一

    一.常用的正则表达式 1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种 ...

  7. IDLE激活方法

    激活流程 一.通过Activation code 方式激活, 注册码获取地址为:http://idea.lanyus.com/ 在idea或者pycharm的Activation code中输入 注册 ...

  8. 利尔达NB-IOT的PSM和eDRX低功耗模式笔记

    1. NB-IOT的技术优势,广覆盖,NB-IOT与GPRS和LTE相比较,最大链路预算提升了20dB,相当于提升了100倍,即使在地车车库.地下室.地下管道等普通无线网络信号难以到达的地方也容易覆盖 ...

  9. 部署:阿里云ECS部署Docker CE

    1 部署阿里云ECS,选择CentOS操作系统,并启动实例: 2 部署Docker CE: a.检查centos版本: $ cat /etc/redhat-release CentOS Linux r ...

  10. jmeter使用beanshell构造参数化

    1.先在本地写一个java类,用来随机生成一个数字,如: package com.jmeter.test; public class BeanShellTest { public int getRan ...