您的位置:首页 > 其它

Codeforces 853B Round #433 Div2D& Div1B Jury Meeting:差分前缀和+模拟

2017-09-07 20:27 281 查看
题意:有n(<=1e5)个城市和一个首都(0号城市),现在每个城市有一个选手,总共有m(<=1e5)次航班,每个航班要么从首都起飞,要么飞到首都去。每个飞机当天飞当天到。且坐飞机这一天什么也不能干,只能等飞机。每个飞机有一个花费和起飞时间。现在要把所有人集中到首都k(<=1e6)天,然后让他们各自回家。求最小花费,如果不可能实现k天或者不能回家了。或者去不了首都等等都输出-1。

题解:每个人可以先处理出一个极大可行区间,就是说我在[ dl , dr ]这段时间可以在首都呆着(保证有飞机接送),就是区间∪。然后所有人的区间取∩就是大家都在首都的最大可行区间了。如果有解,这个区间长度必须大于k。当获得了这个区间的时候,也就知道了所有的可行方案。假如一个方案是在start以及之前到达,在start+k+1以及之后离开。那么每个人显然应该选择[1 , start]时间内最便宜的飞机 和 [start+k+1 , 1e6]时间内最便宜的飞机。那么显然。。我们只需要对每个人把去和回的飞机遍历完一遍,就可以逐段确定答案了。那么这个任务交给前缀和用差分来搞。然后剩下的任务就是在可行区间内枚举答案了。

思路挺easy的。。。但是我这个菜鸡比赛时候一个多小时都没写好。。。。抠脚

Code:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 1e5+100;
const int MAXK = 1e6+100;
typedef long long LL;
int m,n,k;
bool solved = false;
vector<pair<int,int> > a[MAX],b[MAX];
bool cmp(const pair<int,int> a,const pair<int,int>b){
return a.first<b.first;
}
LL ansl[MAXK],ansr[MAXK];
LL res;
int ll,rr;
void input(){
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;i++){
int d,f,t,c;
scanf("%d%d%d%d",&d,&f,&t,&c);
if (f==0){
b[t].push_back(make_pair(d,c));
}else{
a[f].push_back(make_pair(d,c));
}
}
}
void init(){
ll = -1;
rr = 0x3f3f3f3f;
for (int i=1;i<=n;i++){
sort(a[i].begin(),a[i].end(),cmp);
sort(b[i].begin(),b[i].end(),cmp);
int dl = 0x3f3f3f3f;
int dr = -1;
for (vector<pair<int,int> >::iterator it = a[i].begin();it!=a[i].end();++it){
dl = min(dl,it->first);
}
for (vector<pair<int,int> >::iterator it = b[i].begin();it!=b[i].end();++it){
dr = max(dr,it->first);
}
if (dl==0x3f3f3f3f||dr==-1){
solved = true;
printf("-1\n");
return;
}
ll = max (ll,dl);
rr = min(rr,dr);
}
if (ll==-1||rr==0x3f3f3f3f){
solved = true;
printf("-1\n");
}
}
void solve(){
if (solved){
return;
}
if (rr-ll-1<k){
printf("-1\n");
return ;
}
memset(ansl,0,sizeof ansl);
memset(ansr,0,sizeof ansr);
res = 0x3f3f3f3f3f3f3f3fLL;
for (int i=1;i<=n;i++){
int now = 1;
int cost = 0x3f3f3f3f;
for (int t = 0;t<a[i].size();++t){
int temp = a[i][t].first;
//			cout<<"start "<<now<<" "<<temp<<" "<<cost<<endl;
ansl[temp]-=cost;
ansl[now]+=cost;
now = temp;
cost = min(cost,a[i][t].second);
}
ansl[(int)(1e6)+1]-=cost;
ansl[now]+=cost;
now =1e6;
cost = 0x3f3f3f3f;
for (int t = b[i].size()-1;t>=0;--t){
int temp = b[i][t].first;
//			cout<<"end "<<temp<<" "<<now<<" "<<cost<<endl;
ansr[now+1]-=cost;
ansr[temp+1]+=cost;
now = temp;
cost = min(cost,b[i][t].second);
}
ansr[1]+=cost;
ansr[now+1]-=cost;
}
for (int i=1;i<=1e6;i++){
ansl[i]+=ansl[i-1];
ansr[i]+=ansr[i-1];
}
for (int start = ll;start+k+1<=rr;start++){
res = min(res,ansl[start]+ansr[start+k+1]);
//		cout<<"ans "<<start<<" "<<start+k+1<<" : "<<ansl[start]<<" "<<ansr[start+k+1]<<endl;
}
printf("%I64d\n",res);
}
int main(){
//	freopen("output.txt","w",stdout);
input();
init();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息