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$ ($1 \leq i \leq N$) has a shelter which can contain up to $A_i$ 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 $L_i,L_i+1,\cdots,R_i$. 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.

$1 \leq N,Q \leq 2 \times 10^5$

题解

$q$次询问, 每次给一个区间$[l,r]$, 询问$\max_{l≤x≤r}f(l,r,x)$的值.

• $\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

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

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(){
for(int i=1;i<=n;++i){
s1[i]=s1[i-1]+x,s2[i]=s2[i-1]+x*i;
}
for(int i=1;i<=n;++i) bound[i]=find(i);