[SDOI2009]虔诚的墓主人
题目描述
小W是一片新造公墓的管理人。公墓可以看成一块N×M的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地。
当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地。为了体现自己对主的真诚,他们希望自己的墓地拥有着较高的虔诚度。
一块墓地的虔诚度是指以这块墓地为中心的十字架的数目。一个十字架可以看成中间是墓地,墓地的正上、正下、正左、正右都有恰好k棵常青树。
小W希望知道他所管理的这片公墓中所有墓地的虔诚度总和是多少。
输入输出格式
输入格式:输入文件religious.in的第一行包含两个用空格分隔的正整数N和M,表示公墓的宽和长,因此这个矩形公墓共有(N+1) ×(M+1)个格点,左下角的坐标为(0, 0),右上角的坐标为(N, M)。
第二行包含一个正整数W,表示公墓中常青树的个数。
第三行起共W行,每行包含两个用空格分隔的非负整数xi和yi,表示一棵常青树的坐标。输入保证没有两棵常青树拥有相同的坐标。
最后一行包含一个正整数k,意义如题目所示。
输出格式:输出文件religious.out仅包含一个非负整数,表示这片公墓中所有墓地的虔诚度总和。为了方便起见,答案对2,147,483,648取模。
输入输出样例
说明
图中,以墓地(2, 2)和(2, 3)为中心的十字架各有3个,即它们的虔诚度均为3。其他墓
地的虔诚度为0。
对于30%的数据,满足1 ≤ N, M ≤ 1,000。
对于60%的数据,满足1 ≤ N, M ≤ 1,000,000。
对于100%的数据,满足1 ≤ N, M ≤ 1,000,000,000,0 ≤ xi ≤ N,0 ≤ yi ≤ M,1 ≤ W ≤ 100,000,1 ≤ k ≤ 10。
存在50%的数据,满足1 ≤ k ≤ 2。
存在25%的数据,满足1 ≤ W ≤ 10000。
对于一个墓地,以它为中心的十字架的个数为
$C_l^{k}*C_r^{k}*C_u^{k}*C_d^{k}$
$l,r,u,d$分别表示四个方向的树的数量
先离散,按x第一关键词,y为第二关键词排序
枚举x坐标相同的两个点,然后树状数组维护两个点之间的
$C_l^{k}*C_r^{k}$
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 typedef long long lol; 8 const int N=3e5; 9 struct Node 10 { 11 lol x,y; 12 }a[N+5],p[N+5]; 13 lol Mod=2147483648; 14 lol num,n,k,R,C; 15 lol c[N+5],b[N+5],Co[N+5][16],r[N+5],l[N+5],ans; 16 bool cmp(Node a,Node b) 17 { 18 if (a.x==b.x) 19 return a.y<b.y; 20 return a.x<b.x; 21 } 22 void add(int x,lol d) 23 { 24 while (x<=num) 25 { 26 c[x]+=d; 27 c[x]%=Mod; 28 x+=(x&(-x)); 29 } 30 } 31 lol query(int x) 32 { 33 lol s=0; 34 while (x) 35 { 36 s+=c[x]; 37 s%=Mod; 38 x-=(x&(-x)); 39 } 40 return s; 41 } 42 int main() 43 {int i,j,ed,cnt; 44 cin>>R>>C; 45 cin>>n; 46 for (i=1;i<=n;i++) 47 { 48 scanf("%lld%lld",&a[i].x,&a[i].y); 49 b[++num]=a[i].x;b[++num]=a[i].y; 50 } 51 cin>>k; 52 sort(b+1,b+num+1); 53 num=unique(b+1,b+num+1)-b-1; 54 for (i=1;i<=n;i++) 55 { 56 a[i].x=lower_bound(b+1,b+num+1,a[i].x)-b; 57 a[i].y=lower_bound(b+1,b+num+1,a[i].y)-b; 58 } 59 sort(a+1,a+n+1,cmp); 60 Co[1][1]=Co[1][0]=1; 61 for (i=2;i<=100000;i++) 62 { 63 Co[i][0]=1; 64 for (j=1;j<=min(15,i);j++) 65 { 66 Co[i][j]=(Co[i-1][j-1]+Co[i-1][j])%Mod; 67 } 68 } 69 for (i=1;i<=n;i++) 70 r[a[i].y]++; 71 for (i=1;i<=n;i=ed+1) 72 { 73 ed=i;cnt=0; 74 p[++cnt]=a[i]; 75 while (ed+1<=n&&(a[ed+1].x==a[ed].x)) p[++cnt]=a[ed+1],ed++; 76 for (j=1;j<=cnt;j++) 77 { 78 lol y=p[j].y; 79 add(y,(Co[l[y]+1][k]*Co[r[y]-1][k]%Mod-Co[l[y]][k]*Co[r[y]][k]%Mod+Mod)%Mod); 80 l[y]++;r[y]--; 81 if (j>k&&cnt-j+1>=k) 82 ans+=Co[j-1][k]*Co[cnt-j+1][k]%Mod*((query(y-1)-query(p[j-1].y)+Mod)%Mod)%Mod; 83 ans%=Mod; 84 } 85 } 86 cout<<ans; 87 }