按套路,把原答案式转化
\[Ans=T*F(T) -\sum_{i=0}^{T-1}F(i) \]\(F(i)\) 表示 \(i\) 时刻矩形的面积交
考虑没有交集的情况,则
\(F(i)=(2i+1)^2\) 为二次函数
若有交集,相交面积仍为二次函数
二次函数的差依然是二次函数
那总得来说,\(F\) 为一个分段二次函数
段数只有 \(n^2\) 级别
我们可以暴力处理处每一段的前几个 \(F\) 函数前缀和函数(三次函数)
最后直接插出该区间的右端点的前缀和就好了
《矩形面积交》
Code
namespace STG {
#define lid (id<<1)
#define rid (id<<1|1)
struct TREE { int cov,cnt; } tre[255000<<1];
inline void clear(int id,int l,int r) {
tre[id].cnt=tre[id].cov=0;
if(l==r) { return ; }
int mid=(l+r)>>1;
clear(lid,l,mid); clear(rid,mid+1,r);
}
inline void update(int id,int l,int r) {
tre[id].cov= tre[id].cnt? (q2[r]-q2[l-1]+mol)%mol:(tre[lid].cov+tre[rid].cov)%mol;
}
inline void cover(int id,int l,int r,int ll,int rr,int val) {
if(ll<=l&&r<=rr) {
if(!(tre[id].cnt+=val)) { tre[id].cov= (l==r)? 0:(tre[lid].cov+tre[rid].cov)%mol; }
else tre[id].cov=(q2[r]-q2[l-1]+mol)%mol;
return ;
}
int mid=(l+r)>>1;
if(ll<=mid) cover(lid,l,mid,ll,rr,val);
if(rr>mid) cover(rid,mid+1,r,ll,rr,val);
update(id,l,r);
}
inline int query() { return tre[1].cov; }
}
vector<WOS>vec[255000];
inline void ad(int &x) { x= x >= mol ? x-=mol:x; }
inline int cals(int t) {
tot2=0;
for(re int i=1,x,y;i<=n;i++) {
q2[++tot2]=dat[i].x+t;
q2[++tot2]=dat[i].x-t-1;
q2[++tot2]=dat[i].y-t-1;
q2[++tot2]=dat[i].y+t;
}
for(re int i=1;i<=tot2;i++) vec[i].clear();
sort(q2+1,q2+1+tot2); tot2=unique(q2+1,q2+1+tot2)-q2-1;
for(re int i=1,up,dn,le,ri;i<=n;i++) {
up=lower_bound(q2+1,q2+1+tot2,dat[i].y+t)-q2;
dn=lower_bound(q2+1,q2+1+tot2,dat[i].y-t-1)-q2+1;
le=lower_bound(q2+1,q2+1+tot2,dat[i].x-t-1)-q2;
ri=lower_bound(q2+1,q2+1+tot2,dat[i].x+t)-q2;
vec[le].push_back((WOS){ dn,up,1 });
vec[ri].push_back((WOS){ dn,up,-1 });
}
STG::clear(1,1,tot2);
int res=0;
for(re int i=1;i<=tot2;i++) {
(res+=(q2[i]-q2[i-1])%mol*STG::query()%mol)%=mol;
for(re int j=0;j<vec[i].size();j++) {
STG::cover(1,1,tot2,vec[i][j].l,vec[i][j].r,vec[i][j].opt);
}
}
return res;
}