题意:
给你N个矩形,每个矩形给出左下角坐标,右上角坐标,有M个询问,每个询问给出一个时间t,问(0,0),(t,t)的范围内矩形的面积和(重叠的也算)。
分析:
首先我们观察到求的是(0,0),(t,t)的范围内矩形的面积和(重叠的也算)。
①这是一个正方形,那么我们可以尝试将其转换成一个线段。
(因为n≤20000)
②注意“重叠的面积”。
于是我们分成三个阶段。
在这个阶段,计算面积的公式为(t−x1)∗(t−y1),因式分解之后,得到三个系数的值。这种情况是max(x1,y1)<min(x2,y2),所以更新的区间是[max(x1,y1),min(x2,y2)]。
在这个阶段,计算的公式为(t−x1)∗(t−y1)−(t−x1)∗(t−y2),同样因式分解之后,得到三个系统的值。这种情况更新的区间要小心,应该是[max(x1,y2)+1,x2]。另外一种矩阵情况也是一样的,不再赘述。
最后,面积就应为(x2−x1)∗(y2−y1)。更新的范围就是max(x2,y2)+1。
然后就可以用线段树高兴地维护ax2+bx+c的值了
代码:
#include<cstdio>
#include<cstring>
using namespace std;
const long long N=2000100;
long long n,m,x1,y1,x2,y2,t;
struct tree{long long l,r,a,b,c;}g[4*N];
long long max(long long x,long long y){return x>y?x:y;}
long long min(long long x,long long y){return x<y?x:y;}
void build(long long rt,long long l,long long r)
{
g[rt].a=g[rt].b=g[rt].c=0;
g[rt].l=l;g[rt].r=r;
if (l==r) return;
long long mid=(l+r)/2;
build(2*rt,l,mid);
build(2*rt+1,mid+1,r);
}
void pushdown(long long rt)
{
g[2*rt].a+=g[rt].a;
g[2*rt].b+=g[rt].b;
g[2*rt].c+=g[rt].c;
g[2*rt+1].a+=g[rt].a;
g[2*rt+1].b+=g[rt].b;
g[2*rt+1].c+=g[rt].c;
g[rt].a=g[rt].b=g[rt].c=0;
}
long long query(long long rt,long long k)
{
long long l=g[rt].l,r=g[rt].r;
if (l==r) return k*k*g[rt].a+k*g[rt].b+g[rt].c;
long long mid=(l+r)/2;
pushdown(rt);
if (k<=mid)
return query(2*rt,k); else
return query(2*rt+1,k);
}
void update(long long rt,long long ll,long long rr,long long a,long long b,long long c)
{
long long l=g[rt].l,r=g[rt].r;
if (ll<=l && r<=rr)
{
g[rt].a+=a;
g[rt].b+=b;
g[rt].c+=c;
return;
}
long long mid=(l+r)/2;
if (ll<=mid) update(2*rt,ll,rr,a,b,c);
if (rr> mid) update(2*rt+1,ll,rr,a,b,c);
}
int main()
{
long long T;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
build(1,1,200000);
for (long long i=1;i<=n;i++)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
update(1,max(x2,y2)+1,200000,0,0,(x2-x1)*(y2-y1));
if (x2<y2)
update(1,max(x2,y1)+1,y2,0,x2-x1,y1*(x1-x2)); else
update(1,max(x1,y2)+1,x2,0,y2-y1,x1*(y1-y2));
if (max(x1,y1)<min(x2,y2))
update(1,max(x1,y1),min(x2,y2),1,-(x1+y1),x1*y1);
}
scanf("%d",&m);
for (long long i=1;i<=m;i++)
{
scanf("%I64d",&t);
printf("%I64d\n",query(1,t));
}
}
return 0;
}