这种大水题,我还是没有想出来,明明都知道了是差分了。。。。
好了我们来看看,先将有重叠的区间(房子)合并(反正效果都一样),这样我们就得到了多段不重叠的区间。
然后我们枚举每一个点和每一条线段,比如说我们枚举了p这个点它在x,还有两段分别在x1,y1的一条线段,很明显我们最终如果移动的位置在x1-x~y1-x之间的话这个点是会为答案做贡献的,所以我们相当于给一个数组的x1-x~y1-x这一段加上一,最后看看哪个位置值最大,因为之前的区间已经是不重叠了,所以不必担心一个点会被多次计数。
复杂度O(nm),可以过了。
下面是程序
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #define maxm 1009 #define maxn 10009 #define maxx 1000009 using namespace std; struct ding{ int l,r; }a[maxm],c[maxm]; int cnt,b[maxn],n,m,p,ans[maxx+maxx+100],now2,now; bool cmp(ding x,ding y) { return x.l==y.l?x.r<y.r:x.l<y.l; } int main() { //freopen("plan6.in","r",stdin); //freopen("plan.out","w",stdout); scanf("%d%d",&n,&m); cnt=0; for (int i=1;i<=n;i++) scanf("%d",&b[i]); for (int i=1;i<=m;i++) scanf("%d%d",&a[i].l,&a[i].r); sort(a+1,a+1+m,cmp); ding tot=a[1]; for(int i=2;i<=m;i++) if (a[i].l<=tot.r) tot.r=max(tot.r,a[i].r); else c[++cnt]=tot,tot=a[i]; c[++cnt]=tot; for (int i=0;i<=maxx+maxx;i++) ans[i]=0; for (int i=1;i<=n;i++) for (int j=1;j<=cnt;j++) { ans[c[j].l-b[i]+maxx]++; ans[c[j].r-b[i]+1+maxx]--; //cout<<ans[c[j].l-b[i]+maxx]<<" "<<ans[c[j].r-b[i]+1+maxx]<<endl; } now2=maxx;p=0; for (int i=1;i<=maxx+maxx;i++) { p+=ans[i]; if (p>now) { now2=abs(i-maxx); now=p; } if (p==now) now2=min(abs(i-maxx),now2); } printf("%d %d",now2,now); return 0; }