BZOJ2670 : Almost
求出前缀和$s[]$,那么区间$[l,r]$的几乎平均数$=\frac{s[r]-s[l-1]}{r-l}$。
若只有一个询问,那么可以维护$(i,s[i-1])$的凸壳,在凸壳上二分点$(i,s[i])$的切线。
对于多个询问,考虑分块,那么只需要暴力处理零碎部分即可。
时间复杂度$O(n\sqrt{m}\log n)$。
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010,M=30010,K=500,inf=2000010;
typedef long long ll;
int n,m,i,x,f[N],L,R;ll s[N],a[N],b[N];
struct E{int l,r,p;}e[M];
inline bool cmp(const E&a,const E&b){return f[a.l]==f[b.l]?a.r<b.r:f[a.l]<f[b.l];}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
struct P{
ll u,d;
P(){}
P(ll _u,ll _d){u=_u,d=_d;}
bool operator<(const P&b){return u*b.d<d*b.u;}
void reset(){u=-inf,d=1;}
void write(){
if(!u)puts("0/1");
else{
ll t=gcd(u>0?u:-u,d);
printf("%lld/%lld\n",u/t,d/t);
}
}
}ans[M],best,tmp,now;
struct HullA{
int q[N],t;
void init(){t=0;}
void add(int x){
while(t>1&&(a[q[t]]-a[q[t-1]])*(x-q[t])>=(a[x]-a[q[t]])*(q[t]-q[t-1]))t--;
q[++t]=x;
}
void ask(int x,P&ans){
if(!t)return;
int l=2,r=t,o=1,mid;
while(l<=r){
mid=(l+r)>>1;
if((a[q[mid]]-a[q[mid-1]])*(x-q[mid])<=(b[x]-a[q[mid]])*(q[mid]-q[mid-1]))l=(o=mid)+1;else r=mid-1;
}
now=P(b[x]-a[q[o]],x-q[o]);
if(ans<now)ans=now;
}
}hA,tA;
struct HullB{
int q[N],t;
void init(){t=0;}
void add(int x){
while(t>1&&(b[q[t]]-b[q[t-1]])*(x-q[t])<=(b[x]-b[q[t]])*(q[t]-q[t-1]))t--;
q[++t]=x;
}
void ask(int x,P&ans){
if(!t)return;
int l=1,r=t-1,o=t,mid;
while(l<=r){
mid=(l+r)>>1;
if((b[q[mid+1]]-b[q[mid]])*(q[mid]-x)<=(b[q[mid]]-a[x])*(q[mid+1]-q[mid]))r=(o=mid)-1;else l=mid+1;
}
now=P(b[q[o]]-a[x],q[o]-x);
if(ans<now)ans=now;
}
}hB;
inline void read(int&a){
char c;bool f=0;a=0;
while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
if(c!='-')a=c-'0';else f=1;
while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
if(f)a=-a;
}
inline void vio(int l,int r){
tA.init();
tmp.reset();
while(l<=r)tA.ask(l,tmp),tA.add(l++);
}
inline void ask(int l,int r){
while(l<=r)hB.ask(l++,tmp);
}
int main(){
read(n),read(m);
for(i=1;i<=n;i++)read(x),s[i]=s[i-1]+x;
for(i=1;i<=n;i++)a[i]=s[i-1],b[i]=s[i];
for(i=1;i<=n;i++)f[i]=min(((i-1)/K+1)*K,n);
for(i=1;i<=m;i++){
read(e[i].l),read(e[i].r),e[i].p=i;
if(e[i].l+K+5>=e[i].r){
vio(e[i].l,e[i].r);
ans[i]=tmp;
e[i].l=0;
}
}
sort(e+1,e+m+1,cmp);
for(i=1;i<=m;i++)if(e[i].l){
if(f[e[i].l]!=L){
L=f[e[i].l];
R=L-1;
hA.init();
hB.init();
best.reset();
}
while(R<e[i].r)hB.add(++R),hA.ask(R,best),hA.add(R);
vio(e[i].l,L-1);
ask(e[i].l,L-1);
ans[e[i].p]=best<tmp?tmp:best;
}
for(i=1;i<=m;i++)ans[i].write();
return 0;
}
BZOJ2670 : Almost的更多相关文章
随机推荐
- 数据结构c++实现代码-链表
/*节点Node的相关声明与定义*/ //Node.h #include<iostream> using namespace std; template<typename T> ...
- 如果拷贝项目出现各种找不到文件的时候,基本就是没有标记,或者文件名的问题,Could not find resource mybatis.xml,解决方法
Could not find resource mybatis.xml
- Python面向对象 三大特性 综合案例+1(视频里的作业)
class Dog: # 在创建一个小狗实例的时候,给它设置几个属性 def __init__(self, name, age = 1): self.name = name self.age = ag ...
- VS2017+mysql5.7 连接数据库生成实体
参考:https://www.cnblogs.com/RushPasser/p/5438334.html 下载:https://share.weiyun.com/5rM4FrG mysql-for-v ...
- python--使用双向队列结构检查回文
这个简单,队列可两边进两边出. # coding = utf-8 # 双向进出队列 class Deque: def __init__(self): self.items = [] def is_em ...
- [warn] 7#7: *676 a client request body is buffered to a temporary file /var/cache/nginx/client_temp/0000000007
nginx 上传文件遇到的Bug. fastcgi_buffer_size 128k; fastcgi_buffers 8 128k; fastcgi_busy_buffers_size 128k; ...
- javascript OOP实例—探测器
<script> /*所有探测器都有探测的方法和分析的方法,分析当前的浏览器环境,不管是浏览器还是nodejs*/ /*container容器探测器*/ /*link链接探测器*/ /*外 ...
- Java基础知识➣泛型整理(四)
概述 泛型的本质是参数化类型,使用同一套代码来满足不同数据类型的业务需要,提高代码的执行效率,使代码简单明了. 泛型方法 该方法在调用时可以接收不同类型的参数.根据传递给泛型方法的参数类型,编译器适当 ...
- Get与Post区别小结
Get:是以实体的方式得到由请求Url所指定资源的信息,如果请求Url只是一个数据产生过程,那么最终要在实体中返回的是处理过程的结果所指向的资源,而不是处理过程的描述. Post:是用来向 ...
- 今天开始学习php,粘一些重点放这以便查看记忆。
1.PHP的变量用$定义. PHP 将所有全局变量存储在一个名为 $GLOBALS[index] 的数组中. index 保存变量的名称.这个数组可以在函数内部访问,也可以直接用来更新全局变量. 2. ...