• 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) ((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 imes 10^5)

    题解

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

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

    其中(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)的方法是很简单的:

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

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

    (xin[l,mid])那么(pos=l-1),若(xin(mid,r])那么(pos=r+1)

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

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

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

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

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

    时间复杂度是(O(nlog^2n)),利用基数排序可以做到(O(nlog 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],'
    ');
    	return 0;
    }
    
  • 相关阅读:
    根据IP地址查找MAC地址
    MongoDB导入导出以及数据库备份
    本地mongodb数据库导出到远程数据库中
    datatable自动增加序号
    IDEA出现无法加载主类
    远程连接本地mongodb 数据库
    js将后台传入得时间格式化
    Java蓝桥杯--基础练习 (6)回文数
    Java蓝桥杯--基础练习(5)杨辉三角形
    Java蓝桥杯--基础练习(4)查找整数
  • 原文地址:https://www.cnblogs.com/autoint/p/13399912.html
Copyright © 2020-2023  润新知