zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    mysql连接error,Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection .....
    ng-model绑定的是ng-option中的什么?
    js的原型prototype究竟是什么?
    git给log设置别名来快速查看友好的log信息
    git常见使用场景总结
    $http设置headers来实现IE不缓存url请求的资源
    给sublime设置格式化代码的快捷键
    HTTP权威指南 ·
    《编写高质量代码:Web 前端开发修炼之道》 笔记与读后感
    怎么删除git本地分支以及Bitbucket的远程分支?
  • 原文地址:https://www.cnblogs.com/autoint/p/13399912.html
Copyright © 2011-2022 走看看