zoukankan      html  css  js  c++  java
  • Codeforces 909C Python Indentation:树状数组优化dp

    题目链接:http://codeforces.com/contest/909/problem/C

    题意:

      Python是没有大括号来标明语句块的,而是用严格的缩进来体现。

      现在有一种简化版的Python,只有两种语句:

        (1)'s'语句:Simple statements. 相当于一般语句。

        (2)'f'语句:For statements. 相当于for循环,并且规定它的循环体不能为空。

      然后给你一段没有缩进的Python程序,共n行(n <= 5000)。

      问你添加缩进后,有多少种合法且不同的Python程序。

     

    题解:

      表示状态:

        dp[i][j] = numbers

        考虑到第i行,并且第i行的缩进有j个Tab时的合法方案数。

     

      找出答案:

        ans = ∑ dp[n-1][0 to n-1]

        行号从0开始标。并且对于第i行来说,它的缩进最多有i个Tab。

     

      如何转移:

        两种情况。

        当前为dp[i][j](用顺推)。

        (1)第i行为'f',则第i+1行的缩进只能为j+1。

          dp[i+1][j+1] += dp[i][j]

        (2)第i行为's',则第i+1行的缩进可以为[0,j]中的任意一种。

          dp[i+1][0 to j] += dp[i][j]

     

      边界条件:

        dp[0][0] = 1

        第0行的缩进只能为0。

     

      树状数组优化:

        如果按照上面的方程直接去写的话,枚举状态为O(N^2),转移的第二种情况复杂度为O(N)。

        所以最坏情况下为O(N^3),对于N = 5000肯定炸了……

        所以考虑用树状数组来实现转移的第二种情况,也就是区间加法和单点查询。

        于是总复杂度变为O(N^2*logN)。

        另外,树状数组下标从1开始,所以之前所有的下标都要+1。

     

      update:

        其实顺推也可以用差分优化掉一个n的啊……

        (打比赛的时候人是瓷的……)

     

    AC Code:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <string.h>
     4 #define MAX_N 5005
     5 #define MOD 1000000007
     6 
     7 using namespace std;
     8 
     9 int n;
    10 int dp[MAX_N][MAX_N];
    11 char c[MAX_N];
    12 
    13 void update(int *dat,int k,int x)
    14 {
    15     while(k>0)
    16     {
    17         dat[k]=(dat[k]+x)%MOD;
    18         k-=k&-k;
    19     }
    20 }
    21 
    22 int query(int *dat,int k)
    23 {
    24     int sum=0;
    25     while(k<=n)
    26     {
    27         sum=(sum+dat[k])%MOD;
    28         k+=k&-k;
    29     }
    30     return (sum%MOD+MOD)%MOD;
    31 }
    32 
    33 void sec(int *dat,int l,int r,int x)
    34 {
    35     update(dat,r,x);
    36     update(dat,l-1,-x);
    37 }
    38 
    39 int main()
    40 {
    41     cin>>n;
    42     for(int i=1;i<=n;i++) cin>>c[i];
    43     memset(dp,0,sizeof(dp));
    44     sec(dp[1],1,1,1);
    45     for(int i=1;i<=n;i++)
    46     {
    47         for(int j=1;j<=i;j++)
    48         {
    49             int now=query(dp[i],j);
    50             if(now)
    51             {
    52                 if(c[i]=='f')
    53                 {
    54                     sec(dp[i+1],j+1,j+1,now);
    55                 }
    56                 else
    57                 {
    58                     sec(dp[i+1],1,j,now);
    59                 }
    60             }
    61         }
    62     }
    63     int ans=0;
    64     for(int i=1;i<=n;i++)
    65     {
    66         ans=(ans+query(dp[n],i))%MOD;
    67     }
    68     cout<<ans<<endl;
    69 }
  • 相关阅读:
    jquery的ztree操作
    原创-使用pywinauto和swapy-ob-0.4.3进行dotnet的winform程序控制(二)
    原创-使用pywinauto进行dotnet的winform程序控制(一)
    javascript“命名空间”的费曼输出[原创]
    IIS7上传4M文件以上文件出现“Post大小超出允许的限制”错误解决方法
    OpenProj打开不了或者提示”Failed to load Java VM Library”的错误的解决方案
    项目管理中,开始到完成、完成到开始、开始到开始、和完成到完成的关系图解
    我的项目管理之干系人分析在单位项目中的运用
    关于学习js的Promise的心得体会
    vue.js与后台模板引擎“双花括号”冲突时的解决办法
  • 原文地址:https://www.cnblogs.com/Leohh/p/8135525.html
Copyright © 2011-2022 走看看