zoukankan      html  css  js  c++  java
  • [HNOI2012]双十字

    题目描述

    在C 部落,双十字是非常重要的一个部落标志。所谓双十字,如下面两个例子,由两条水平的和一条竖直的”1“线段组成,要求满足以下几个限制: ![] 我们可以找到 5 个满足条件的双十字,分别如下:  注意最终的结果可能很大,只要求输出双十字的个数 mod 1,000,000,009 的值·两条水平的线段不能在相邻的两行。·竖直线段上端必须严格高于两条水平线段,下端必须严格低于两条水平线段。 ·竖直线段必须将两条水平线段严格划分成相等的两半。·上方的水平线段必须严格短于下方的水平线段。 所以上面右边的例子是满足要求的最小的双十字。现在给定一个 R*C的01 矩阵,要求计算出这个 01 矩阵中有多少个双十字。例如下面这个例子,R=6,C=8,01 矩阵如下:

    输入输出格式

    输入格式:

    第一行为用空格隔开的两个正整数 R和C,分别表示01矩阵的行数和列数。输入文件第二行是一个非负整数N,表示01矩阵中”0“的个数。接下来的N行,每行为用空格隔开的两个正整数x和y(1<=x<=R,1<=y<=C),表示(x,y)是一个”0“。数据保证N个”0“的坐标两两不同。数据保证R,C,N<=10,000,R*C<=1,000,000.(事实上R*C可能稍大于原设定)

    输出格式:

    D mod 1,000,000,009 的结果,其中D 为要求的 01矩阵中双十字的个数。

    输入输出样例

    输入样例#1: 复制
    6  8
    12
    1  2
    1  3
    1  4
    1  6
    2  2
    3  2
    3  3
    3  4
    3  7
    6  4
    6  6
    4  8
    输出样例#1: 复制
    5
    因为10000×10000存不下,所以用编号代替坐标
    首先DP求出L,R,U,D数组表示左右上下有多少个连续的1
    一个点左右可拓展的长度应当是min(L,R)
    枚举十字架中心在第几列
    当了某一行,考虑以它作于下面一个横线的方案数
    $sum_{len=1}^{L[i]} min(L[j], len-1)×D[i]×(j-top)$
    把min拆掉:
    1.当len-1<=L[j],则$sum_{len=1}^{L[i]} L[j]×D[i]×(j-top)$
    2.当len-1>L[j],则$sum_{len=1}^{L[i]} (len-1)×D[i]×(j-top)$
    可以变成:
    1.当L[j]<=L[i],贡献$(L[i]-(L[j]+1)/2)×D[i]×(j-top)×L[j]$
    2.当L[j]>L[i],贡献$L[i]×(L[i]-1)/2×D[i]×(j-top)$
    维护3个树状数组,分别维护:
    $(j-top)$
    $(j-top)*L[j]$
    $(j-top)*L[j]*L[j]$
    每一次碰到0或算完一列的答案要给树状数组清0
    因为十字架上面的横线不能是i-1,所以考虑先算完i,再加入i-1
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 using namespace std;
      6 int mp[1500001],U[1500001],D[1500001],L[1500001],R[1500001],n,r,c;
      7 int Mod=1e9+9,f1[50001],f2[50001],f3[50001],inv2,top,ans,ed;
      8 int get_id(int x,int y)
      9 {
     10   return c*(x-1)+y;
     11 }
     12 int qpow(int x,int y)
     13 {
     14   int res=1;
     15   while (y)
     16     {
     17       if (y&1) res=1ll*res*x%Mod;
     18       x=1ll*x*x%Mod;
     19       y>>=1;
     20     }
     21   return res;
     22 }
     23 void add1(int x,int d,int N)
     24 {
     25   if (x==0) return;
     26   while (x<=N)
     27     {
     28       f1[x]+=d;
     29       if (f1[x]>=Mod) f1[x]-=Mod;
     30       x+=x&(-x);
     31     }
     32 }
     33 void add2(int x,int d,int N)
     34 {
     35   if (x==0) return;
     36   while (x<=N)
     37     {
     38       f2[x]+=d;
     39       if (f2[x]>=Mod) f2[x]-=Mod;
     40       x+=x&(-x);
     41     }
     42 }
     43 void add3(int x,int d,int N)
     44 {
     45   if (x==0) return; 
     46   while (x<=N)
     47     {
     48       f3[x]+=d;
     49       if (f3[x]>=Mod) f3[x]-=Mod;
     50       x+=x&(-x);
     51     }
     52 }
     53 int query1(int x)
     54 {
     55   int s=0;
     56   while (x)
     57     {
     58       s+=f1[x];
     59       if (s>=Mod) s-=Mod;
     60       x-=(x&(-x));
     61     }
     62   return s;
     63 }
     64 int query2(int x)
     65 {
     66   int s=0;
     67   while (x)
     68     {
     69       s+=f2[x];
     70       if (s>=Mod) s-=Mod;
     71       x-=(x&(-x));
     72     }
     73   return s;
     74 }
     75 int query3(int x)
     76 {
     77   int s=0;
     78   while (x)
     79     {
     80       s+=f3[x];
     81       if (s>=Mod) s-=Mod;
     82       x-=(x&(-x));
     83     }
     84   return s;
     85 }
     86 int get_van(int x,int y,int N)
     87 {
     88   int t=L[get_id(x,y)];
     89   int as=0;
     90   int s2=query2(t),s3=query3(t);
     91     as=(1ll*t*s2%Mod-1ll*(s3+s2)%Mod*inv2%Mod+Mod);
     92   if (as>=Mod) as-=Mod;
     93   int s1=(query1(N)-query1(t)+Mod);
     94   if (s1>=Mod) s1-=Mod;
     95   as=(as+1ll*t*(t-1)%Mod*inv2%Mod*s1%Mod);
     96   if (as>=Mod) as-=Mod;
     97   return 1ll*as*D[get_id(x,y)]%Mod;
     98 }
     99 void update(int x,int y,int N)
    100 {
    101   int t=L[get_id(x,y)];
    102   add1(t,x-top,N);
    103   add2(t,1ll*(x-top)*t%Mod,N);
    104   add3(t,1ll*(x-top)*t%Mod*t%Mod,N);
    105 }
    106 int main()
    107 {int i,j,x,y,l;
    108   cin>>r>>c;
    109   cin>>n;
    110   inv2=qpow(2,Mod-2);
    111   memset(mp,-1,sizeof(mp));
    112   for (i=1;i<=n;i++)
    113     {
    114       scanf("%d%d",&x,&y);
    115       mp[get_id(x,y)]=0;
    116     }
    117   for (i=1;i<=r;i++)
    118     {
    119       for (j=1;j<=c;j++)
    120       {
    121         if (mp[get_id(i,j)]==-1)
    122           mp[get_id(i,j)]=1;
    123       }
    124     }
    125   for (i=1;i<=r;i++)
    126     {
    127       L[get_id(i,1)]=0;
    128       for (j=2;j<=c;j++)
    129       if (mp[get_id(i,j-1)]==1&&mp[get_id(i,j)]==1) L[get_id(i,j)]=L[get_id(i,j-1)]+1;
    130       else L[get_id(i,j)]=0;
    131       R[get_id(i,c)]=0;
    132       for (j=c-1;j>=1;j--)
    133       if (mp[get_id(i,j+1)]==1&&mp[get_id(i,j)]==1) R[get_id(i,j)]=R[get_id(i,j+1)]+1;
    134       else R[get_id(i,j)]=0;
    135       for (j=1;j<=c;j++)
    136       L[get_id(i,j)]=min(L[get_id(i,j)],R[get_id(i,j)]);
    137     }
    138   for (j=1;j<=c;j++)
    139     {
    140       U[get_id(1,j)]=0;
    141       for (i=2;i<=r;i++)
    142       if (mp[get_id(i-1,j)]==1&&mp[get_id(i,j)]==1) U[get_id(i,j)]=U[get_id(i-1,j)]+1;
    143       else U[get_id(i,j)]=0;
    144       D[get_id(r,j)]=0;
    145       for (i=r-1;i>=1;i--)
    146       if (mp[get_id(i+1,j)]==1&&mp[get_id(i,j)]==1) D[get_id(i,j)]=D[get_id(i+1,j)]+1;
    147       else D[get_id(i,j)]=0;
    148     }
    149   for (j=1;j<=c;j++)
    150     {top=0;
    151       ed=min(c-j,j-1);
    152       for (l=0;l<=ed;l++)
    153     f1[l]=f2[l]=f3[l]=0;
    154       for (i=1;i<=r;i++)
    155       {
    156         if (top==0&&mp[get_id(i,j)]==1) top=i;
    157         if (mp[get_id(i,j)]==0&&top)
    158           {
    159             for (l=0;l<=ed;l++)
    160           f1[l]=f2[l]=f3[l]=0;
    161             top=0;
    162             continue;
    163           }
    164         if (top==0) continue;
    165         if (i==top) continue;
    166         if (i-top>=3&&L[get_id(i,j)]>1)
    167           {
    168             ans=ans+get_van(i,j,ed);
    169             if (ans>=Mod) ans-=Mod;
    170           }
    171         if (i-1!=top&&L[get_id(i-1,j)]>0)
    172           update(i-1,j,ed);
    173       }
    174     }
    175   cout<<ans;
    176 }
  • 相关阅读:
    dxCalloutPopup 简单使用教程
    Delphi INI文件保存与读取
    AlertWindowManager 弹出提示窗口使用帮助(下)
    AlertWindowManager 弹出提示窗口使用帮助(上)
    可输入弹出窗口-[POPUP_GET_VALUES_USER_HELP]
    [BAPI]采购申请PR审批-BAPI_REQUISITION_RELEASE_GEN
    如何取域值 (当一些业务需要的值只有数字或者字母时 ,汉字描述在域里面)
    采购订单、采购申请审批策略相关表
    [BAPI]如何修改工单状态-BAPI_ALM_ORDER_MAINTAIN
    [函数]读取采购订单、采购申请更改历史-ME_CHANGEDOC_READ2
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8537602.html
Copyright © 2011-2022 走看看