题目大意:维护一个等腰直角三角形(两条直角边贴着坐标轴),支持子等腰直角三角形(两条直角边和坐标轴垂直)加1和求和。
n
≤
1
0
3
,
Q
≤
1
0
5
,
3
s
n\le10^3,Q\le10^5,3s
n≤103,Q≤105,3s
题解:发现n非常小,传统数据结构没有优势。
考虑如果所有修改在询问之前,只要每个询问和每个之前的修改取个交即可。
那么设有q次修改,每s次修改后暴力重构前缀和数组,询问时从前缀和里得到重构前的答案,然后没加进去的像刚刚那样手动办平面交即可。
这样重构的总复杂度是
O
(
q
s
(
n
s
+
n
2
)
)
=
O
(
q
n
+
q
n
2
s
)
O\left(\frac qs\left(ns+n^2\right)\right)=O\left(qn+\frac{qn^2}{s}\right)
O(sq(ns+n2))=O(qn+sqn2),询问总复杂度
O
(
Q
(
n
+
s
)
)
O(Q(n+s))
O(Q(n+s)),这样大约取
s
=
q
Q
n
s=\sqrt{\frac qQ}n
s=Qqn即可做到
O
(
Q
n
+
n
q
Q
)
=
O
(
n
q
)
O\left(Qn+n\sqrt{qQ}\right)=O(nq)
O(Qn+nqQ)=O(nq)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define gc getchar()
#define lint long long
#define N 1010
#define Q 100010
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
lint ps[N][N],vs[N][N];
struct Query{
int tp,x,y,a;
}q[Q];int usv[Q];
inline int rebuild(int n,int updc)
{
for(int i=1;i<=updc;i++)
{
int x=q[usv[i]].x,y=q[usv[i]].y,a=q[usv[i]].a;
for(int j=0;j<=a&&x+j<=n;j++)
vs[x+j][y]++,vs[x+j][y+j+1]--;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++) vs[i][j]+=vs[i][j-1];
for(int j=1;j<=i;j++) vs[i][j]+=vs[i][j-1];
for(int j=1;j<=i;j++) ps[i][j]+=vs[i][j],vs[i][j]=0;
}
return 0;
}
inline lint query_Int(int d1,int l1,int a1,int d2,int l2,int a2,int n)
{
int d=min(d1+a1,d2+a2),l=max(l1,l2);d=min(d,n),l=min(l,n);
int b=max(d1-l1+1,d2-l2+1),it=d-b+1,len=it-l+1;
if(it<l) return 0;return len*(len+1ll)/2;
}
int main()
{
int n=inn(),qc=inn(),updtot=0,s=0;
for(int i=1;i<=qc;i++)
q[i].tp=inn(),q[i].x=inn(),q[i].y=inn(),q[i].a=inn()-1,updtot+=(q[i].tp==1);//notice I've a--!!!!!!!!!!!!!!!!
s=(int)(n*sqrt((double)updtot/qc)*2);
// debug(updtot)sp,debug(s)ln;
for(int i=1,updcnt=0;i<=qc;i++)
if(q[i].tp==1) usv[++updcnt]=i,(updcnt>=s?rebuild(n,updcnt),updcnt=0:0);
else{
int x=q[i].x,y=q[i].y,a=q[i].a;lint ans=0ll;
for(int j=0;j<=a&&x+j<=n;j++)
ans+=ps[x+j][y+j]-ps[x+j][y-1];
for(int j=1;j<=updcnt;j++)
ans+=query_Int(x,y,a,q[usv[j]].x,q[usv[j]].y,q[usv[j]].a,n);
printf("%lld\n",ans);
}
return 0;
}