[bzoj1227]虔诚的墓主人
离散化+扫描线,树状数组维护当前列 每一行的左边右边各取k个的方案数
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int ui;
ui mod=2147483648ll;
const int N=1e5+5;
int n,m,w,k;
ui ans=0;
ui c[N][20];
int cnt[N];
inline void cinit(){
c[0][0]=1;
for(int i=1;i<=w;i++)c[i][0]=1;
for(int i=1;i<=w;i++)if(i<=k)c[i][i]=1;
for(int i=1;i<=w;i++)
for(int j=1;j<=min(i-1,k);j++){
c[i][j]=(c[i-1][j]+c[i-1][j-1]);
}
}
/*--------------------------------*/
struct node{
int x,y;
}nd[N];
inline bool cmpx(const node a,const node b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
inline bool cmpy(const node a,const node b){
if(a.y==b.y) return a.x<b.x;
return a.y<b.y;
}
int XX[N];
inline void renumber(){
sort(nd+1,nd+w+1,cmpx);
n=1;XX[1]=n;
for(int i=2;i<=w;i++){
if(nd[i].x!=nd[i-1].x)n++;
XX[i]=n;
}
for(int i=1;i<=w;i++)nd[i].x=XX[i];
sort(nd+1,nd+w+1,cmpy);
m=1;XX[1]=m;
for(int i=2;i<=w;i++){
if(nd[i].y!=nd[i-1].y)m++;
XX[i]=m;
}
for(int i=1;i<=w;i++)nd[i].y=XX[i];
}
int l[N],r[N];
/*---------------------------------*/
#define lowbit(x) (x&(-x))
ui t[N];
inline void add(int x,ui y){
for(;x<=n;x+=lowbit(x)){
t[x]+=y;
}
}
inline ui qy(int x){
ui ret=0;
for(;x;x-=lowbit(x)){
ret+=t[x];
}
return ret;
}
inline ui ask(int l,int r){
if(l>r)return 0;
l--;
return qy(r)-qy(l);
}
inline void change(int x,ui y){
ui lst=ask(x,x);
add(x,y-lst);
}
/*---------------------------------*/
int main()
{
scanf("%d%d",&n,&m);
scanf("%d",&w);
for(int i=1;i<=w;i++)
scanf("%d%d",&nd[i].x,&nd[i].y);
scanf("%d",&k);
renumber();
for(int i=1;i<=w;i++)r[nd[i].x]++;
cinit();
int p=1;
for(int Y=1;Y<=m;Y++)if(nd[p].y==Y){
int u=p,v=p;
while(nd[v].y==Y&&v<=w)v++;
p=v;v--;
for(int i=u;i<=v;i++){
r[nd[i].x]--;
int L=l[nd[i].x],R=r[nd[i].x];
change(nd[i].x,c[L][k]*c[R][k]);
}
int S=v-u+1;
for(int i=k;S-i>=k;i++){
int cur=u+i-1;
int upnum=i,downnum=S-i;
ui s=ask(nd[cur].x+1,nd[cur+1].x-1);
ans=ans+s*c[upnum][k]*c[downnum][k];
}
for(int i=u;i<=v;i++){
l[nd[i].x]++;
int L=l[nd[i].x],R=r[nd[i].x];
change(nd[i].x,c[L][k]*c[R][k]);
}
}
printf("%u\n",ans%mod);
}