• Codeforces Ilya and Queries


    递推(DP)

    http://codeforces.com/contest/313/problem/B

    题意:比较好懂,一个字符串只有.或者#字符,给你一段区间[x,y],其实y>x,让你在这个区间里面统计一个数字,即这个子串,相邻两位,若s[i]=s[i+1]则计数一次,然后输出结果

    这题一看,其实想到了线段树,因为原串,如果一段连续的.....则看成是一串白色的段,一段连续的#####则看成是一段黑色的段,那么原串可以看成是线段树的总区间被一系列的黑白段覆盖,对于每个查询就在线段树上查询它被什么黑白段覆盖,并且覆盖了多长,不过鉴于比赛时间短,而且好像大材小用的感觉,就没再往线段树上面想,比赛后看到这题真被归为数据结构,男单真的是线段树?或者其他的?

    不过正解觉得应该是用递推水过,dp[i]表示从1到i,有多少个相邻的s[x] = s[x+1]

    递推方程很好写

    dp[1] = 0

    if       s[i] = s[i-1]     dp[i] = dp[i-1] + 1

    else                         dp[i] = dp[i-1]

    对于一个查询[x,y],则一步可以查到,即dp[y] - dp[x]

    但是还要处理一下接口处,如果s[x] = s[x-1],那么还要减掉1

    不难看代码,我再想想怎么用数据结构写

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define N 100010
    
    int dp[N],n;
    char s[N];
    
    int main()
    {
        scanf("%s",s+1);
        n = strlen(s+1);
        dp[0] = dp[1] = 0;
        for(int i=2; i<=n; i++)
            dp[i] = (s[i] == s[i-1]) ? dp[i-1]+1 : dp[i-1];
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int res = dp[y] - dp[x-1];
            if(x!=1 && s[x] == s[x-1]) res--;
            printf("%d\n",res);
        }
        return 0;
    }
  • 相关阅读:
    mongodb协议透传
    [转]PyInstaller2的信息文件Version的生成
    [转]使用PyInstaller2将Python脚本转化为可执行文件(中使用部分)
    Cache应用(sql依赖缓存)
    关于Cookie与Session的疑问解答
    ADO.NET Entity Framework
    WPF中的画笔功能,实现直实线、弯实线、直虚线、弯虚线
    Singleton模式之多线程
    控件回发系列一(IPostBackEventHandler)
    使用VS2010创建EntityDataModel出错
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3109671.html
Copyright © 2020-2023  润新知