• bzoj1227: [SDOI2009]虔诚的墓主人(树状数组,组合数)


    传送门

    首先,对于每一块墓地,如果上下左右各有$a,b,c,d$棵树,那么总的虔诚度就是$C_k^a*C_k^b*C_k^c*C_k^d$

    那么我们先把所有的点都给离散,然后按$x$为第一关键字,$y$为第二关键字,那么同一横坐标的一定在连续的一段且纵坐标递增

    那么对于同一横坐标的两棵常青树,在他们中间的所有空地都有可能满足条件,因为上面的常青树和下面的常青树数量是固定的,所以$C_k^a*C_k^b$的值也是固定的

    那么我们就是需要快速求出一段区间里的$C_k^c*C_k^d$,那么我们可以考虑用树状数组来维护。这部分细节可以参考代码

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define int long long
     6 using namespace std;
     7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     8 char buf[1<<21],*p1=buf,*p2=buf;
     9 inline int read(){
    10     #define num ch-'0'
    11     char ch;bool flag=0;int res;
    12     while(!isdigit(ch=getc()))
    13     (ch=='-')&&(flag=true);
    14     for(res=num;isdigit(ch=getc());res=res*10+num);
    15     (flag)&&(res=-res);
    16     #undef num
    17     return res;
    18 }
    19 const int N=100005,mod=2147483648;
    20 int n,m,k,C[N][15],tt=0,ans,tmp[N],c[N],col,tot[N],cnt[N],r[N],h[N];
    21 struct node{int x,y;}a[N];
    22 inline bool cmp(const node &a,const node &b)
    23 {return a.x!=b.x?a.x<b.x:a.y<b.y;}
    24 inline bool cmp2(const node &a,const node &b)
    25 {return a.y!=b.y?a.y<b.y:a.x<b.x;}
    26 inline void add(int x,int y){
    27     for(;x<=col;x+=x&-x) (c[x]+=y)%=mod;
    28 }
    29 inline int query(int x){
    30     int res=0;
    31     for(;x;x-=x&-x) (res+=c[x])%=mod;
    32     return res;
    33 }
    34 signed main(){
    35     //freopen("testdata.in","r",stdin);
    36     read();read();n=read();
    37     for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read();
    38     k=read();
    39     for(int i=0;i<=n;++i) C[i][0]=1;
    40     for(int i=1;i<=n;++i)
    41     for(int j=1;j<=min(i,k);++j)
    42     C[i][j]=C[i-1][j]+C[i-1][j-1];
    43     sort(a+1,a+1+n,cmp2);
    44     for(int i=1;i<=n;++i)
    45     tmp[i]=(i==1||a[i].y!=a[i-1].y)?++tt:tt;
    46     for(int i=1;i<=n;++i) cnt[a[i].y=tmp[i]]++;col=a[n].y;
    47     sort(a+1,a+1+n,cmp);
    48     for(int i=1;i<=n;++i)
    49     tmp[i]=(i==1||a[i].x!=a[i-1].x)?++tt:tt;
    50     for(int i=1;i<=n;++i) tot[a[i].x=tmp[i]]++;
    51     for(int i=1;i<=n;++i){
    52         if(i==1||a[i].x!=a[i-1].x) tt=0;
    53         int dy=a[i].y,v=(++h[dy])>=k&&cnt[dy]-h[dy]>=k?
    54         1ll*C[h[dy]][k]*C[cnt[dy]-h[dy]][k]%mod:0;++tt;
    55         add(dy,v-r[dy]),r[dy]=v;
    56         if(i==n||a[i].x!=a[i+1].x||a[i+1].y-a[i].y<=1
    57         ||tt<k||tot[a[i].x]-tt<k) continue;
    58         (ans+=1ll*C[tt][k]*C[tot[a[i].x]-tt][k]%mod
    59         *(query(a[i+1].y-1)-query(a[i].y)))%=mod;
    60     }
    61     printf("%d
    ",(ans>=0?ans:ans+mod)%mod);
    62     return 0;
    63 }
  • 相关阅读:
    POJ 3419 Difference Is Beautiful (DP + 二分 + rmq)
    CodeForces 755C PolandBall and Forest (并查集)
    CodeForces 754D Fedor and coupons (优先队列)
    CodeForces 753C Interactive Bulls and Cows (Hard)
    CodeForces 754C Vladik and chat (DP+暴力)
    HDU 1996 汉诺塔VI (排列组合)
    HDU 1995 汉诺塔V (水题)
    HDU 2077 汉诺塔IV (递推)
    HDU 2064 汉诺塔III (递推)
    How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9598137.html
Copyright © 2020-2023  润新知