zoukankan      html  css  js  c++  java
  • [Offer收割]编程练习赛10简略题解

    题目1 : 出勤记录I(水题)

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Hi的算法课老师每次上课都会统计小Hi的出勤记录。迟到会被记录一个L,缺席会被记录一个A,按时上课会被记录一个O。

    一学期结束,小Hi的出勤记录可以看成是一个只包含LAO的字符串,例如"OOOOLOOOLALLO……"。

    如果小Hi整学期缺席不超过1次,并且没有连续3次迟到,小Hi的出勤记录就算合格。  

    现在给出小Hi的出勤记录,你能判断他是否合格么?

    输入

    输入第一行包含一个整数T(1 <= T <= 10),代表测试数据的组数。  

    以下T行每行一个程度不超过100的字符串S,代表小Hi的出勤记录。

    输出

    对于每一份出勤记录,输出YES或者NO表示该份记录是否合格。

    样例输入
    3
    LLOLLALL  
    OLLLOOOO  
    OOAAOOOO
    样例输出
    YES  
    NO  
    NO
    判断是否有“LLL”出现或者"A"出现的个数超过两次 输出NO,其他为YES

    题目2 : 出勤记录II(dp)

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Hi的算法课老师每次上课都会统计小Hi的出勤记录。迟到会被记录一个L,缺席会被记录一个A,按时上课会被记录一个O。

    一学期结束,小Hi的出勤记录可以看成是一个只包含LAO的字符串,例如"OOOOLOOOLALLO……"。

    如果小Hi整学期缺席不超过1次,并且没有连续3次迟到,小Hi的出勤记录就算合格。  

    现在给出字符串的长度N,小Hi想知道长度为N的出勤记录中,合格的记录总共有多少种。  

    例如长度为3的合格出勤记录有19种:OOO OOL OOA OLO OAO LOO AOO OLL OLA OAL LOL LOA AOL LLO LAO ALO LLA LAL ALL。

    输入

    一个整数N(1 <= N <= 100000)。

    输出

    长度为N的合格记录总数。由于结果可能很大,你只需输出结果模109+7的余数。

    样例输入
    3

    样例输出
    19
    可以用dp[i][A][L]表示长度为N序列的串,“A”出现的个数为A, 末尾连续“L”的个数为L个
    if(s[i+1] == 'L' && L <= 2 && L >= 1) dp[i+1][A][L] += dp[i][A][L-1]
    if( s[i+1] == 'A') dp[i+1][1][0] += dp[i][0][L]
    if( s[i+1] == 'O') dp[i+1][A][0] += dp[i][A][L]
    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <map>
    
    using namespace std;
    const int MAXN = 2e5+10;
    int A[MAXN], cnt[MAXN];
    int n;
    typedef long long int LL;
    LL k;
    map<int, int>Map;
    LL slove(LL ans){
        LL ret = 0, sum = 0;
        for(int i = 0, j = 0; i < n; i++){
            while(j < n && sum+cnt[A[j]] <= ans)    {
                sum += cnt[A[j]];
                cnt[A[j]]++;
                j++;
            }
            ret += j-i;
            cnt[A[i]]--;
            sum -= cnt[A[i]];
        }
        return ret;
    }
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n, &k);
            for(int i = 0; i < n; i++){
                scanf("%d", &A[i]);
                Map[A[i]] = i;
            }
            for(int i = 0; i < n; i++) A[i] = Map[A[i]];
            LL L = -1, R = 1LL*n*(n+1);
            while(L + 1 < R){
                LL mid = (L+R)>>1;
                if(slove(mid) < k) L = mid;
                else R = mid;
            }
            printf("%lld
    ", R);
        }
        return 0;
    }

    题目3 : 区间价值(二分+双指针)

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    给定n个数A1...An,小Ho想了解AL..AR中有多少对元素值相同。小Ho把这个数目定义为区间[L,R]的价值,用v[L,R]表示。

    例如1 1 1 2 2这五个数所组成的区间的价值为4。

    现在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少。

    输入

    第一行一个数T(T<=10),表示数据组数。

    对于每一组数据:

    第一行两个数n,k(1<=n<=200,000,1<=k<=n*(n+1)/2)

    第二行n个数A1…An(1<=Ai<=1,000,000,000)

    输出

    一个数表示答案。

    样例输入
    2
    4 7
    1 1 2 3
    3 6
    100 100 100
    样例输出
    0
    3


    二分答案,用双指针求出[1~n]区间 <= ans的个数

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <map>
    
    using namespace std;
    const int MAXN = 2e5+10;
    int A[MAXN], cnt[MAXN];
    int n;
    typedef long long int LL;
    LL k;
    map<int, int>Map;
    LL slove(LL ans){
        LL ret = 0, sum = 0;
        //ret 小于等于ans区间的个数
        for(int i = 0, j = 0; i < n; i++){
            while(j < n && sum+cnt[A[j]] <= ans)    {
                sum += cnt[A[j]];
                cnt[A[j]]++;
                j++;//指针j向右移动
            }
            ret += j-i;//求出满足条件区间的 个数  
            cnt[A[i]]--;//指针i向右移动
            sum -= cnt[A[i]];
        }
        return ret;
    }
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n, &k);
            for(int i = 0; i < n; i++){
                scanf("%d", &A[i]);
                Map[A[i]] = i;
            }
            for(int i = 0; i < n; i++) A[i] = Map[A[i]];//使A[i]处在[0~n-1]
            LL L = -1, R = 1LL*n*(n+1);
            while(L + 1 < R){
                LL mid = (L+R)>>1;
                if(slove(mid) < k) L = mid;
                else R = mid;
            }
            printf("%lld
    ", R);
        }
        return 0;
    }
    
    
  • 相关阅读:
    day 66 crm(3) 自创组件stark界面展示数据
    day 65 crm(2) admin源码解析,以及简单的仿造admin组件
    用 Python+nginx+django 打造在线家庭影院
    django -admin 源码解析
    day 64 crm项目(1) admin组件的初识别以及应用
    云链接 接口不允许 情况 解决方法 mysql Host is not allowed to connect to this MySQL server解决方法
    day 56 linux的安装python3 ,虚拟环境,mysql ,redis
    day55 linux 基础以及系统优化
    Codeforces 989 P循环节01构造 ABCD连通块构造 思维对云遮月参考系坐标轴转换
    Codeforces 990 调和级数路灯贪心暴力 DFS生成树两子树差调水 GCD树连通块暴力
  • 原文地址:https://www.cnblogs.com/cshg/p/6582483.html
Copyright © 2011-2022 走看看