【题目描述】:
在平面直角坐标系上晒了许多块被子,被子呈矩形,边均与x或y轴平行,在(0,0)处有一个水源,水不断从(0,0)处溢出,在第t秒形成了一个以(0,0)(0,t)(t,0)(t,t)为顶点的正方形水域,在其中的被子都会被弄湿,询问某些时刻被弄湿的被子的总面积(同一格子的不同被子算多次)。
【输入描述】:
第一行2个整数n、q,表示被子总数和询问次数。
接下来n行每行4个整数x1、y1、x2、y2,表示一条被子的位置是以(x1,y1)(x2,y2)为左下角和右上角顶点的矩形。
接下来q行每行1个整数t,表示询问第t秒被子弄湿的总面积。
【输出描述】:
共q行表示每次询问的答案。
【样例输入】:
3 3
0 0 3 3
1 0 3 2
0 1 2 3
1
2
3
【样例输出】:
1
8
17
【样例说明】:
样例输入说明,下载图片
【时间限制、数据范围及描述】:
时间:1s 空间:256M
30%的数据0<=t,x1,y1,x2,y2<=1000。
50%的数据n<=1000,q<=1000。
另有20%的数据q=1。
100%的数据n<=50000,q<=100000,0<=t,x1,y1,x2,y2<=5×10^6,x1<x2,y1<y2。
【code】
1 #include <cstdio> 2 int n,m,i,x1,y1,x2,y2,t,l,a[500001],b[500001],c[500001],x,d[400001]; 3 long long t1,t2,tot,s,s2,ss,ans[100001]; 4 bool p[400001]; 5 void add(int x,int y,int z) 6 { 7 if (x>y) t=x,x=y,y=t;s+=z; 8 ++l;a[l]=x;b[l]=(l+1)/2;c[l]=z; 9 ++l;a[l]=y;b[l]=l/2;c[l]=z; 10 } 11 void kp(int l,int r) 12 { 13 int i=l,j=r,m=a[(i+j)/2]; 14 while (i<=j) 15 { 16 while (a[i]<m) ++i; 17 while (a[j]>m) --j; 18 if (i<=j) 19 { 20 t=a[i];a[i]=a[j];a[j]=t; 21 t=b[i];b[i]=b[j];b[j]=t; 22 t=c[i];c[i]=c[j];c[j]=t; 23 ++i;--j; 24 } 25 } 26 if (i<r) kp(i,r);if (l<j) kp(l,j); 27 } 28 int main() 29 { 30 scanf("%d%d",&n,&m);s=0; 31 for (i=1;i<=n;++i) 32 { 33 scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 34 if (x2>0&&y2>0) add(x2,y2,1); 35 if (x1>0&&y2>0) add(x1,y2,-1); 36 if (x2>0&&y1>0) add(x2,y1,-1); 37 if (x1>0&&y1>0) add(x1,y1,1); 38 } 39 for (i=1;i<=m;++i) 40 { 41 scanf("%d",&x);++l;a[l]=x;b[l]=i;c[l]=0; 42 } 43 kp(1,l);tot=0;s2=0;a[0]=0; 44 for (i=1;i<=l;++i) 45 { 46 t1=a[i-1];t2=a[i];ss=t2*t2-t1*t1; 47 tot+=ss*s;ss=(t2-t1)*s2;tot+=ss; 48 if (c[i]==0) ans[b[i]]=tot;else 49 if (!p[b[i]]) 50 { 51 s2+=a[i]*c[i];s-=c[i];p[b[i]]=true;d[b[i]]=a[i]; 52 } else s2-=d[b[i]]*c[i]; 53 } 54 for (i=1;i<=m;++i) printf("%lld\n",ans[i]); 55 }