zoukankan      html  css  js  c++  java
  • bzoj 1227: [SDOI2009]虔诚的墓主人

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define ll long long
     5 #define P 2147483648LL
     6 using namespace std;
     7 int n,m,w,K,H[200001];
     8 ll c[100001][11],tr[200001],ans;
     9 struct data{int x,y;}a[100005];
    10 int h[200001],l[200001];
    11 int now[200001];
    12 int find(int x)
    13 {
    14     int l=1,r=2*w,mid;
    15     while(l<=r)
    16     {
    17          int mid=(l+r)>>1;
    18          if(H[mid]<x)l=mid+1;
    19          else if(H[mid]>x)r=mid-1;
    20          else return mid;
    21               } 
    22 }
    23 void getc()
    24 {
    25       c[0][0]=1;
    26       for(int i=1;i<=w;i++)
    27       {c[i][0]=1;
    28          for(int j=1;j<=min(K,i);j++)
    29             c[i][j]=(c[i-1][j]+c[i-1][j-1])%P;
    30           }
    31 }
    32 int lowbit(int x){return x&(-x);}
    33 void update(int x,int y)
    34 {
    35      while(x<=2*w)
    36      {
    37                 tr[x]+=y;tr[x]%=P;
    38                 x+=lowbit(x);
    39                 }
    40      }
    41 ll ask(int x)
    42 {
    43      ll s=0;
    44      while(x)
    45      {
    46              s+=tr[x];s%=P;
    47              x-=lowbit(x);
    48              }
    49      return s;
    50      }
    51 inline bool cmp(data a,data b)
    52 {
    53       if(a.y==b.y)return a.x<b.x;
    54     return a.y<b.y;
    55 }
    56 int main()
    57 {
    58      scanf("%d%d%d",&m,&n,&w);
    59      for(int i=1;i<=w;i++)
    60      {
    61         scanf("%d%d",&a[i].x,&a[i].y);
    62         H[2*i-1]=a[i].x;
    63         H[2*i]=a[i].y;
    64       }
    65    scanf("%d",&K);getc();
    66    sort(H+1,H+2*w+1);
    67    for(int i=1;i<=w;i++)
    68    {
    69         h[find(a[i].y)]++;
    70         l[find(a[i].x)]++;
    71    }
    72    sort(a+1,a+w+1,cmp);
    73    int lf;
    74    for(int i=1;i<=w;i++)
    75    {
    76       if(i>1&&a[i].y==a[i-1].y)
    77       {
    78          lf++;
    79          ll t1=ask(find(a[i].x)-1)-ask(find(a[i-1].x));
    80                ll t2=c[lf][K]*c[h[find(a[i].y)]-lf][K];
    81                ans+=t1*t2;
    82          ans%=P;
    83         }
    84         else lf=0;
    85       int d=find(a[i].x);now[d]++;
    86       int change=(c[now[d]][K]*c[l[d]-now[d]][K]-c[now[d]-1][K]*c[l[d]-now[d]+1][K])%P;
    87       update(d,change);
    88    }
    89    if(ans<0)ans+=P;
    90    printf("%d",ans);
    91      return 0;
    92 }

    树状数组,预处理出每一行 每一列的坟墓数 将坐标按x,y排序。一行一行扫,用树状数组存一段区间上下方案数相乘,按顺序扫时,能顺便求出左右,这样再乘上这段区间的树状数组

    即可。树状数组修改时先减去原值,在加。

  • 相关阅读:
    0x02 枚举、模拟、递推
    0x01 位运算
    bzoj3529: [Sdoi2014]数表
    bzoj5216: [Lydsy2017省队十连测]公路建设
    POJ1789Truck History
    最小生成树模板
    POJ1258Agri-Net
    POJ1860Currency Exchange(SPFA)
    POJ3083Children of the Candy Corn
    POJ2503Babelfish
  • 原文地址:https://www.cnblogs.com/xydddd/p/5243722.html
Copyright © 2011-2022 走看看