【题目描述】:
在平面直角坐标系上晒了许多块被子,被子呈矩形,边均与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
下载
代码:
#include
#include
#include
#include
using namespace std;
const int N=500010;
bool p[N];
int a[N],b[N],c[N],d[N];
int n,m,t,l,x,x1,x2,y1,y2;
long long t1,t2,tot,s,ss,s2,ans[N];
void add(int x,int y,int z) {
if(x>y)
swap(x,y);
s+=z;
l++;
a[l]=x;
b[l]=(l+1)/2;
c[l]=z;
l++;
a[l]=y;
b[l]=l/2;
c[l]=z;
}
void kp(int l,int r) {
int i=l,j=r,m=a[(i+j)/2];
while(i<=j) {
while(a[i]m)
j--;
if(i<=j) {
swap(a[i],a[j]);
swap(b[i],b[j]);
swap(c[i],c[j]);
i++;
j--;
}
}
if(i0&&y2>0)
add(x2,y2,1);
if(x1>0&&y2>0)
add(x1,y2,-1);
if(x2>0&&y1>0)
add(x2,y1,-1);
if(x1>0&&y1>0)
add(x1,y1,1);
}
for(int i=1; i<=m; i++) {
scanf("%d",&x);
l++;
a[l]=x;
b[l]=i;
c[l]=0;
}
kp(1,l);
tot=0;
s2=0;
a[0]=0;
for(int i=1; i<=l; i++) {
t1=a[i-1];
t2=a[i];
ss=t2*t2-t1*t1;
tot+=ss*s;
ss=(t2-t1)*s2;
tot+=ss;
if(c[i]==0)
ans[b[i]]=tot;
else if(!p[b[i]]) {
s2+=a[i]*c[i];
s-=c[i];
p[b[i]]=true;
d[b[i]]=a[i];
} else
s2-=d[b[i]]*c[i];
}
for(int i=1; i<=m; i++)
printf("%lld\n",ans[i]);
return 0;
}