zoukankan      html  css  js  c++  java
  • 2016 Multi-University Training Contest 4

    2016 Multi-University Training Contest 1

    这次比赛名次算是目前来最好的一次了,总共A了6题,几乎全是dp题。真是佩服一神。

    HDU5763 Another Meaning  (kmp+dp)

    这道题开场后五分钟一神就给我们过来讲解法,我思考了好一会儿才理解。

    kmp预处理出子串p。对于父串,当枚举当i时,如果t[i]是p的后缀,那么就dp[i] = (dp[i-m]+dp[i])%mod,(m是子串的长度)。即要么和t[i]相连的串变成*(此时个数是dp[i-m]个),要么和t[i]相连的串不变,那就继承前面的dp[i-1].(前面已有dp[i] = dp[i-1]).

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5+5;
    const ll mod = 1000000007;
    char p[maxn];
    char t[maxn];
    int n,m;
    ll dp[maxn];
    int Next[maxn];
    void getNext()
    {
        int k = -1;
        int j = 0;
        Next[0] = -1;
        while(j<m)
        {
            if(k == -1||p[k]==p[j])
            {
                k++;
                j++;
                Next[j] = k;
            }
            else k = Next[k];
        }
    }
    void kmp()
    {
        getNext();
        int i = 0;
        int j = 0;
        dp[0] = 1;
        while(i<n)
        {
            if(j == -1||t[i]==p[j])
            {
                i++;
                dp[i] = dp[i-1];
                j++;
            }
            else j = Next[j];
            if(j == m)
            {
                if(i>m) dp[i] = (dp[i]+dp[i-m])%mod;
                if(i==m) dp[i] = 2;
                j = Next[j];
            }
        }
    }
    int main()
    {
        int T,kase = 0;cin>>T;
        while(T--)
        {
            scanf("%s",t);
            scanf("%s",p);
            n = strlen(t);
            m = strlen(p);
            kmp();
            printf("Case #%d: ",++kase);
            printf("%d
    ",dp[n]);
        }
        return 0;
    }
    卷珠帘

    HDU5764 After a Sleepless Night

    HDU5765 Bonds

    HDU5766 Filling

    HDU5768 Lucky7

    HDU5769 Substring

    HDU5770 Treasure

    HDU5771 Turn Game

    HDU5772 String problem

    HDU5773 The All-purpose Zero

    这两天真好修炼dp,看完这题感觉和最长上升子序列有点像,就去学O(nlogn)的LIS了,老柴也套了个板子,他改的那一下子我感觉特别巧妙,真服。

    对于是非0的元素,直接像普通的LIS那样处理。

    对于0的元素

    cnt[++len] = cnt[len-1]+1;
    for(int i=len-1;i>1;i--)
    {
    cnt[i] = cnt[i-1]+1;
    }
    cnt[1] = 0;

    举一个例子,比如cnt中现在是1 5 9,这时候a[i]是0,这样处理完后是,0,2,6,10.那么在下一次a[i]非0时,比如a[i]=7,那么这时候插进来,

    得序列0,2,6,7;前面的那个a[i]=0仍然起了增一的作用,即相当于当时使得cnt[3] = 6,插入任何数字那个0都起了作用。

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn = 1e5+5;
    int a[maxn];
    int cnt[maxn];
    int main()
    {
        int t,n,kase = 0;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            int len = 1;
            cnt[len] = a[1];
            for(int i=2;i<=n;i++)
            {
                if(a[i])
                {
                    if(a[i]>cnt[len])
                    {
                        cnt[++len] = a[i];
                    }
                    else
                    {
                        int pos = lower_bound(cnt+1,cnt+len+1,a[i])-cnt;//非递减序列中返回第一个大于等于a[i]的位置
                        cnt[pos] = a[i];
                    }
                }
                else
                {
                    cnt[++len] = cnt[len-1]+1;
                    for(int i=len-1;i>1;i--)
                    {
                        cnt[i] = cnt[i-1]+1;
                    }
                    cnt[1] = 0;
                }
            }
            printf("Case #%d: %d
    ",++kase,len);
        }
        return 0;
    }
    卷珠帘

    HDU5774 Where Amazing Happens

    这道大水题,刚开始我问老柴这题是什么意思,他说就是统计每个人名出现的次数,我说好那不就数一数就行了嘛,他说对呀,我就开始数,结果数了七八个,我就晕了,这人名,好多很难区分啊,机智的我开始用map统计了。o(^▽^)o

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <cstring>
    using namespace std;
    map<char*,int> mp;
    void pre()
    {
        mp["Baltimore Bullets"] = 1;
        mp["Boston Celtics"] = 17;
        mp["Chicago Bulls"] = 6;
        mp["Cleveland Cavaliers"] = 1;
        mp["Dallas Mavericks"] = 1;
        mp["Detroit Pistons"] = 3;
        mp["Golden State Warriors"] = 2;
        mp["Houston Rockets"] = 2;
        mp["L.A. Lakers"] = 11;
        mp["Miami Heat"] = 3;
        mp["Milwaukee Bucks"] = 1;
        mp["Minneapolis Lakers"] = 5;
        mp["New York Knicks"] = 2;
        mp["Philadelphia 76ers"] = 2;
        mp["Philadelphia Warriors"] = 2;
        mp["Portland Trail Blazers"] = 1;
        mp["Rochester Royals"] = 1;
        mp["San Antonio Spurs"] = 5;
        mp["Seattle Sonics"] = 1;
        mp["St. Louis Hawks"] = 1;
        mp["Syracuse Nats"] = 1;
        mp["Washington Bullets"] = 1;
    
    }
    int main()
    {
        pre();
        int t,kase = 0;
        scanf("%d",&t);
        getchar();
        char ss[1004];
        while(t--)
        {
            int flag = 0;
            gets(ss);
            map<char*,int>::iterator it;
            printf("Case #%d: ",++kase);
            for(it = mp.begin(); it!=mp.end();it++)
            {
                if(strcmp(it->first,ss)==0)
                {
                    flag =  1;
                    printf("%d
    ",it->second);
                    break;
                }
            }
            if(!flag) printf("0
    ");
        }
        return 0;
    }
    卷珠帘

    HDU5775 Bubble Sort

    一道统计逆序对的题,和曾经的线段树模板题很像,正好现在再复习下。

    线段树模板:

    #include <iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    const int maxn = 1e5+5;
    int a[maxn];
    struct node{
        int l,r,v;
    };
    node T[maxn*4];
    void build(int l,int r,int q){
        T[q].l = l;
        T[q].r = r;
        if(T[q].l == T[q].r){
            T[q].v = 0;
            return;
        }
        int mid = (l+r)/2;
        build(l,mid,q*2);
        build(mid+1,r,q*2+1);
        T[q].v = T[q*2].v + T[q*2+1].v;
    }
    int sum(int l,int r,int q){
        if(l<=T[q].l&&T[q].r<=r){
            return T[q].v;
        }
        int mid = (T[q].l+T[q].r)/2;
        if(r<=mid) return sum(l,r,q*2);
        if(l>mid) return sum(l,r,q*2+1);
        return sum(l,mid,q*2)+sum(mid+1,r,q*2+1);
    }
    void Add(int i,int j,int q){
        if(T[q].l == T[q].r){
            T[q].v += j;
            return;
        }
        int mid = (T[q].l+T[q].r)/2;
        if(i<=mid) Add(i,j,q*2);
        else Add(i,j,q*2+1);
        T[q].v = T[q*2].v+T[q*2+1].v;
    }
    void input(){
        int T,n,kase = 0,x,w;
        cin>>T;
        while(T--){
            scanf("%d",&n);
            build(1,n,1);
            int ans = 0;
            for(int i = 1; i<=n; i++)
            {
                scanf("%d",&x);
                w = x-i+sum(x,n,1);
                a[x] = max(i+w,x)-min(x,i);
                Add(x,1,1);
            }
            printf("Case #%d:",++kase);
            for(int i = 1; i<=n; i++)
            {
                printf(" %d",a[i]);
            }
            printf("
    ");
        }
    }
    int main()
    {
        input();
        return 0;
    }
    卷珠帘

    树状数组模板:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <map>
    #include <cstring>
    using namespace std;
    # include <stdio.h>
    # include <string.h>
    const int maxn = 1e5+5;
    int a[maxn], b[maxn], n;
    void u(int v){while (v) b[v]++, v -= v & -v;}
    
    
    int q(int v){
        int x = 0;
        while (v <= n) x += b[v], v += v & -v;
        return x;
    }
    
    
    int main()
    {
        int t,kase = 0;
        scanf("%d",&t);
        while(t--)
        {
            memset (b, 0, sizeof(b)) ;
            scanf("%d",&n);
            int x,w;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&x);
                w = x-i+q(x);
                a[x] = max(i+w,x)-min(x,i);
                u(x);
            }
            printf("Case #%d:",++kase);
            for(int i=1;i<=n;i++)
                printf(" %d",a[i]);
            printf("
    ");
        }
        return 0;
    }
    卷珠帘
  • 相关阅读:
    02、Linux下sshd以及openssl的知识点
    01_1、光盘上CentOS 安装程序启动过程
    01_2、GRUB(Boot Loader)
    1.在CentOS 6.4安装python3
    02.python基础知识_02
    01.python基础知识_01
    python_opencv应用系列1:图片读写
    Python for else 循环控制
    python中print后面加逗号
    Python中def的用法
  • 原文地址:https://www.cnblogs.com/littlepear/p/5716000.html
Copyright © 2011-2022 走看看