记录编号 409900 评测结果 AAAAAAAAAA
题目名称 [HNOI 2012]双十字 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 3.321 s
提交时间 2017-05-29 20:32:16 内存使用 61.34 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e6+10,p=1000000009;
int inc(int x,int y){x+=y;return x>=p?x-p:x;}
int dec(int x,int y){x-=y;return x<0?x+p:x;}
int mul(int x,int y){return (ll)x*y%p;}
int c2(int x){return ((ll)x*(x-1)>>1)%p;}
struct bit{
	int a[N];
	void add(int p,int d){
		for (p++;p<N;p+=p&-p) a[p]=inc(a[p],d);
	}
	int sum(int p){
		int ans=0;
		for (p++;p>0;p-=p&-p) ans=inc(ans,a[p]);
		return ans;
	}
	int sum(int l,int r){
		return dec(sum(r),sum(l-1));
	}
}T;
vector<int> a[N],l[N],r[N],up[N],down[N];
int n,m,k;
void init(vector<int> &a){
	a.push_back(0);
	for (int i=1;i<=m;i++) a.push_back(1);
	a.push_back(0);
}
void start(){
	scanf("%d%d%d",&n,&m,&k);
	for (int i=0;i<m+2;i++){
		a[0].push_back(0);
		l[0].push_back(0);
		r[0].push_back(0);
		up[0].push_back(0);
		down[0].push_back(0);
		a[n+1].push_back(0);
		l[n+1].push_back(0);
		r[n+1].push_back(0);
		up[n+1].push_back(0);
		down[n+1].push_back(0);
	}
	for (int i=1;i<=n;i++){
		init(a[i]);
		init(l[i]);
		init(r[i]);
		init(up[i]);
		init(down[i]);
	}
	for (int i=1;i<=k;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		a[x][y]=0;
	}
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++)
		l[i][j]=a[i][j]?l[i][j-1]+1:0;
	for (int i=1;i<=n;i++)
	for (int j=m;j;j--)
		r[i][j]=a[i][j]?r[i][j+1]+1:0;
	for (int j=1;j<=m;j++)
	for (int i=1;i<=n;i++)
		up[i][j]=a[i][j]?up[i-1][j]+1:0;
	for (int j=1;j<=m;j++)
	for (int i=n;i;i--)
		down[i][j]=a[i][j]?down[i+1][j]+1:0;
	for (int i=1;i<=n;i++)
	for (int j=1;j<=m;j++){
		r[i][j]=min(l[i][j],r[i][j])-1;
		up[i][j]--;
		down[i][j]--;
	}
}
int main()
{
	freopen("bzoj_2727.in","r",stdin);
	freopen("bzoj_2727.out","w",stdout);
	start();
	int ans=0;
	for (int j=1;j<=m;j++){
		//printf("line %d:\n",j);
		int last=1;
		while (last<=n){
			int now=last;
			for (;a[now][j];now++);
			//printf("[%d,%d)\n",last,now);
			for (int i=last+2;i<now;i++){
				T.add(r[i-2][j],up[i-2][j]);
				ans=inc(ans,mul(down[i][j],mul(c2(r[i][j]),T.sum(r[i][j],N-1))));
			}
			for (int i=last+2;i<now;i++)
				T.add(r[i-2][j],p-up[i-2][j]);
			for (int i=last+2;i<now;i++){
				T.add(r[i-2][j],mul(up[i-2][j],r[i-2][j]));
				ans=inc(ans,mul(down[i][j],mul(r[i][j],T.sum(0,r[i][j]-1))));
			}
			for (int i=last+2;i<now;i++)
				T.add(r[i-2][j],p-mul(up[i-2][j],r[i-2][j]));
			for (int i=last+2;i<now;i++){
				T.add(r[i-2][j],mul(up[i-2][j],c2(r[i-2][j]+1)));
				ans=dec(ans,mul(down[i][j],T.sum(0,r[i][j]-1)));
			}
			for (int i=last+2;i<now;i++)
				T.add(r[i-2][j],p-mul(up[i-2][j],c2(r[i-2][j]+1)));
			last=now+1;
		}
	}
	printf("%d\n",ans);
	return 0;
}