Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

Gym102586B Evacuation

Evacuation

There are N+2 towns in a straight line. The towns are numbered from 0 through N+1 from left to right. Each town i (1iN) has a shelter which can contain up to Ai people.

Currently, S people are traveling together and visiting one of the towns. However, you don't know which town they are visiting.

You just got to know that there are Q meteorites that can hit the towns. The i-th meteorite may strike towns Li,Li+1,,Ri. To ensure the safety of the travelers, for each meteorite, you want to calculate the evacuation cost.

The evacuation cost for a meteorite is calculated as follows:

  • The evacuation cost is the minimum total cost needed to make all travelers safe no matter which town they are visiting.

  • A person is safe if he/she is in a shelter or a town outside the effect of the meteorite.

  • It takes 1 unit cost to move one person to an adjacent town (two towns are adjacent iff their numbers differ by exactly 1).
    Note that only moving people costs money, and other actions (like accommodating people in a shelter) don't. It is guaranteed that towns 0 and N+1 will never be affected by meteorites, so it is always possible to make all travelers safe.

Write a program that, for each meteorite, calculates the evacuation cost for that meteorite.

1N,Q2×105

题解

有一个长度为n的序列a和一个常数s.

q次询问, 每次给一个区间[l,r], 询问max的值.

其中f(l,r, x)被定义为, 对于所有满足以下条件的序列b,

  • \sum^n_{i=1} b_i = s

  • ∀l ≤ i ≤ r, b_i ≤ a_i

\sum^n_{i=1} |i − x|b_i的最小可能值

https://www.cnblogs.com/cjoierShiina-Mashiro/p/12800124.html

对于询问f(l,r,x),如果我们固定了x,那么构造最优的b的方法是很简单的:

从小到大枚举i\in[0,+\infty),尽可能地让b_{x-i},b_{x+i}大。

如果在S还没有放完的时候遇到了一个pos\notin[l,r],那么把剩下的S全部放到b_{pos}就行了。

x\in[l,mid]那么pos=l-1,若x\in(mid,r]那么pos=r+1

不难发现x\in[l,mid]f(l,r,x)r无关,x\in(mid,r]f(l,r,x)l无关。

因此设f(l,r,x)=\begin{cases}f(l,x)&x\in[l,mid]\\g(r,x)&x\in(mid,r]\end{cases}

预处理\{a_i\}的前缀和以及\{ia_i\}的前缀和之后可以O(1)的求出单点f,g

观察可得f,g满足四边形不等式。

考虑离线所有询问,对于一个形如\max\limits_{x\in[L,R]}(f\text{ or }g)(r,x)的询问,将其拆分成线段树上的O(\log n)个区间,最后对线段树的每个节点
用决策单调性优化暴力枚举x计算即可。

时间复杂度是O(n\log^2n),利用基数排序可以做到O(n\log n)

CO int N=2e5+10;
int n,q;
int64 s,s1[N],s2[N],ans[N];
int bound[N];
IN int64 sum(int64*s,int l,int r){
return s[r]-s[l-1];
}
int find(int p){
int l=0,r=min(n-p,p-1);
while(l<r){
int mid=(l+r+1)>>1;
sum(s1,p-mid,p+mid)<=s?l=mid:r=mid-1;
}
return l;
}
IN int64 calc(int p,int len){
if(len<=0) return 0;
return sum(s1,p-len,p-1)*p-sum(s2,p-len,p-1)+sum(s2,p+1,p+len)-sum(s1,p+1,p+len)*p;
}
IN int64 calc(int o,int p,int lim){
int f=!o?-1:1;
int t=!o?max(lim-1,p-bound[p]-1):min(lim+1,p+bound[p]+1);
return calc(p,f*(t-p)-1)+(s-(!o?sum(s1,t+1,2*p-(t+1)):sum(s1,2*p-(t-1),t-1)))*f*(t-p);
}
void solve(int o,int l,int r,vector<pair<int,int> >&q){
if(q.empty()) return;
if(l==r){
for(CO pair<int,int>&a:q)
ans[a.second]=max(ans[a.second],calc(o,l,a.first));
return;
}
vector<pair<int,int> > ql,qr;
int mid=q.size()/2,pos=0;
int64 tmp,mx=0;
for(int i=0;i<(int)q.size();++i)if(i!=mid)
i<mid?ql.push_back(q[i]):qr.push_back(q[i]);
for(int i=l;i<=r;++i)
if((tmp=calc(o,i,q[mid].first))>mx) mx=tmp,pos=i;
ans[q[mid].second]=max(ans[q[mid].second],mx);
solve(o,l,pos,ql),solve(o,pos,r,qr);
}
vector<pair<int,int> > trans[4*N][2];
#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
void insert(int x,int l,int r,int ql,int qr,int o,int id){
if(ql>qr) return;
if(ql<=l and r<=qr) return trans[x][o].push_back({!o?ql:qr,id});
if(ql<=mid) insert(lc,l,mid,ql,qr,o,id);
if(qr>mid) insert(rc,mid+1,r,ql,qr,o,id);
}
void query(int x,int l,int r){
for(int i=0;i<2;++i){
sort(trans[x][i].begin(),trans[x][i].end());
solve(i,l,r,trans[x][i]);
}
if(l==r) return;
query(lc,l,mid),query(rc,mid+1,r);
}
#undef lc
#undef rc
#undef mid
int main(){
read(n),read(s);
for(int i=1;i<=n;++i){
int64 x=read<int64>();
s1[i]=s1[i-1]+x,s2[i]=s2[i-1]+x*i;
}
for(int i=1;i<=n;++i) bound[i]=find(i);
read(q);
for(int i=1;i<=q;++i){
int l=read<int>(),r=read<int>(),mid=(l+r)>>1;
insert(1,1,n,l,mid,0,i),insert(1,1,n,mid+1,r,1,i);
}
query(1,1,n);
for(int i=1;i<=q;++i) write(ans[i],'\n');
return 0;
}

posted on   autoint  阅读(340)  评论(0编辑  收藏  举报

编辑推荐:
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
阅读排行:
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
历史上的今天:
2019-07-29 CF286E Ladies' Shop
2019-07-29 test20190729 夏令营NOIP训练14
2019-07-29 UOJ23 跳蚤国王下江南

导航

点击右上角即可分享
微信分享提示