4925: 城市规划
Time Limit: 5 Sec Memory Limit: 256 MBSubmit: 100 Solved: 49
[Submit][Status][Discuss]
Description
最近比特镇正在迅速建成。沿着美丽的大街,一座座新建筑拔地而起。小Q喜欢沿着大街走,但问题是不同的建筑位于街对面。为了从一个建筑到另一个建筑,有时需要通过漫长的步行穿过最近的人行道。所以他决定写一个程序,计算如何沿着大街平移所有人行道,使得人行道的布局最有利于行人。他希望尽可能多的人行道出现在某些建筑物的前面,同时人行道的移动距离应当是最小的。
大街以直线表示,人行道被视为这条线上的点。所有建筑物都平行于大街,所以你可以认为它们是直线上的一条条线段。每条线段都具有左边界和右边界。如果某人行道位于某建筑物的左右边界之间(包括边界点),则你可以认为该人行道位于该建筑物的前方。由于人行道已经按照某些标准建立,小Q决定保持它们之间的距离,所以他想将所有的人行道移动相同的距离。
请帮助小Q写一个程序计算最优布局
Input
第一行包含两个正整数n,m(1<=n<=10000,1<=m<=1000),分别表示人行道和建筑的个数。
第二行包含n个整数a_i(0<=a_i<=10^6),分别表示每条人行道的坐标,可能存在两条人行道重合。
接下来m行,每行两个整数l_i,r_i(0<=l_i<r_i<=10^6),分别表示每座建筑的左右边界,这些线段可以相互重叠。
Output
输出一行两个整数d和s,其中d表示平移距离的绝对值,s表示出现在至少一座建筑物前面的人行道个数。你需要输出s最大的解,若有多个d使得s最大,那么输出d最小的解。注意你可以向左或者向右平移人行道。
Sample Input
4 2
1 6 6 1
4 5
3 5
1 6 6 1
4 5
3 5
Sample Output
1 2
先把线段合并
然后以移动距离为下标把线段对于每个点差分
最后扫一遍就行了
疯狂卡常 最后也只能在内存上略胜一筹 抢个rank1 括弧泪
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<map>
#include<set>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=10100,M=1010;
const int MAXDIS=1e6+5;
struct seg{int l,r;}s[M];
inline bool cmp(const seg &x,const seg &y){return x.l<y.l;}
inline int tabs(int x){return x>0?x:-x;}
int a[N],ans[MAXDIS<<1];
int main()
{
register int i,j,k,n=read(),m=read(),mx=0,D=MAXDIS,mn=0X3f3f3f3f,d,val=0,cnt=1;
for(i=1;i<=n;++i)a[i]=read();
for(i=1;i<=m;++i)s[i].l=read(),s[i].r=read();
sort(s+1,s+1+m,cmp);
for(i=2;i<=m;++i)
if(s[i].l<=s[cnt].r)s[cnt].r=max(s[cnt].r,s[i].r);
else s[++cnt].l=s[i].l,s[cnt].r=s[i].r;
m=cnt;
sort(s+1,s+1+m,cmp);
for(i=1;i<=n;++i)for(j=1;j<=m;++j)
{ans[s[j].l-a[i]+D]++;ans[s[j].r-a[i]+1+D]--;mx=max(s[j].r-a[i]+1+D,mx);mn=min(s[j].l-a[i]+D,mn);}
for(i=mn;i<=mx;++i)
{
ans[i]+=ans[i-1];
if(ans[i]>val)val=ans[i],d=tabs(D-i);
else if(ans[i]==val)d=min(d,tabs(D-i));
}
print(d);putchar(' ');print(val);puts("");return 0;
}
/*
4 2
1 6 6 1
4 5
3 5
1 2
*/