題意:給你N個矩形,每個矩形給出左下角座標,右上方座標,有M個詢問,每個詢問給出一個時間t,問(0,0),(t,t)的範圍內矩形的面積和(重疊的也算)。
用樹狀數組去維護A*t*t+B*t+C這個式子的A,B,C三個係數,維護在不同的t時,ABC分別應該為多少。
分成三個階段。
在這個階段,計算面積的公式為(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。
#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N=200005;typedef long long LL;struct BIT{ LL T[N]; int lowbit(int x) {return x&(-x);} void clear(){memset(T,0,sizeof(T));} void add(int st,int ed,LL valu) { for(int i=st;i<N;i+=lowbit(i)) T[i]+=valu; for(int i=ed+1;i<N;i+=lowbit(i)) T[i]-=valu; } LL query(int pos) { LL sum=0; for(int i=pos;i>0;i-=lowbit(i)) sum+=T[i]; return sum; }}A,B,C;void fun(int st,int ed,LL a,LL b,LL c){ A.add(st,ed,a); B.add(st,ed,b); C.add(st,ed,c);}int main(){ int t; scanf("%d",&t); while(t--) { A.clear(); B.clear(); C.clear(); int n,m; scanf("%d",&n); for(int i=0;i<n;i++) { LL x1,y1,x2,y2; scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2); if(max(x1,y1)<min(x2,y2)) fun(max(x1,y1),min(x2,y2),1,-(x1+y1),x1*y1); if(x2<y2) fun(max(x2,y1)+1,y2,0,-x1+x2,y1*(x1-x2)); if(y2<x2) fun(max(y2,x1)+1,x2,0,-y1+y2,x1*(y1-y2)); fun(max(x2,y2)+1,N,0,0,(x2-x1)*(y2-y1)); } scanf("%d",&m); while(m--) { LL t; scanf("%I64d",&t); LL ans=0; ans+=A.query(t)*t*t; ans+=B.query(t)*t; ans+=C.query(t); printf("%I64d\n",ans); } } return 0;}