[bzoj1227]虔诚的墓主人

[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);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/82882688