cot - 分块

题目大意:维护一个等腰直角三角形(两条直角边贴着坐标轴),支持子等腰直角三角形(两条直角边和坐标轴垂直)加1和求和。 n 1 0 3 , Q 1 0 5 , 3 s n\le10^3,Q\le10^5,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 ( Q ( n + s ) ) O(Q(n+s)) ,这样大约取 s = q Q n s=\sqrt{\frac qQ}n 即可做到 O ( Q n + n q Q ) = O ( n q ) O\left(Qn+n\sqrt{qQ}\right)=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;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82851681
Cot