码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1227: [SDOI2009]虔诚的墓主人

时间:2016-03-05 00:04:00      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:

 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排序。一行一行扫,用树状数组存一段区间上下方案数相乘,按顺序扫时,能顺便求出左右,这样再乘上这段区间的树状数组

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

bzoj 1227: [SDOI2009]虔诚的墓主人

标签:

原文地址:http://www.cnblogs.com/xydddd/p/5243722.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!