zoukankan      html  css  js  c++  java
  • 2015 CCPC-C-The Battle of Chibi (UESTC 1217)(动态规划+树状数组)

    赛后当天学长就说了树状数组,结果在一个星期后赖床时才有了一点点思路……

    因为无法提交,不确定是否正确。。嗯。。有错希望指出,谢谢。。。

    嗯。。已经A了。。提交地址http://acm.uestc.edu.cn/#/problem/show/1217

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    /**
    题意:T代表测试组数 (T<=100)
         每组两个数N, M(1<=N<=1000,1<=M<=N)
         给N个数ai(1<=ai<=10^9)
         求该数列的m长递增子序列
    方法:容易想到dp[i][k]表示到第i个数,长度为k的子序列,O(N^3)可解
         通过树状数组可以优化到O(N^2lgN)
    */
    
    struct node{
        int data;
        int pos;
        bool operator < (const node a) const
        {
            if (data == a.data)
                return pos < a.pos;
            return data < a.data;
        }
    } a[1005];
    
    int c[1005][1005];      // c[k][i] 结尾数字为i,长度为k的子序列数量
    int b[1005];
    int N, M;
    
    const int MOD = 1000000007;
    
    int lowbit(int x)
    {
        return x & (-x);
    }
    
    int sum(int x, int n)
    {
        int ans = 0;
        while (n > 0) {
            ans = (ans + c[x][n]) % MOD;
            n -= lowbit(n);
        }
        return ans;
    }
    
    void plu(int x, int pos, int num)
    {
        while (pos <= N) {
            c[x][pos] = (c[x][pos] + num) % MOD;
            pos += lowbit(pos);
        }
    }
    
    
    int main()
    {
        int t, cas = 0;
        scanf("%d", &t);
        while (t--)
        {
            scanf("%d%d", &N, &M);
            for (int i = 1; i <= N; ++i)
            {
                scanf("%d", &a[i].data);
                a[i].pos = i;
            }
    
            // 离散化
            sort(a + 1, a + N + 1);
            int cnt = 1;
            b[a[1].pos] = cnt;
            for (int i = 2; i <= N; ++i)
            {
                if (a[i].data > a[i - 1].data) cnt++;
                b[a[i].pos] = cnt;
            }
    
            //for (int i = 1; i <= N; ++i) cout << b[i] << endl;
    
            memset(c, 0, sizeof c);
    
            for (int i = 1; i <= N; ++i)
            {
                plu(1, b[i], 1);        // 以每个数结尾的长度为1的数都是1
                for (int k = 2; k <= M; ++k)
                {
                    int temp = sum(k - 1, b[i] - 1); // 所有比b[i]小的数长度为k-1的和就是以b[i]为结尾的长度为k的了。。
                    plu(k, b[i], temp);
                }
            }
    
            int ans = sum(M, N);
            printf("Case #%d: %d
    ", ++cas, ans);
        }
        return 0;
    }
    
    /**
    Input:
    5
    3 2
    1 2 3
    3 2
    3 2 1
    3 1
    1 2 3
    3 2
    1 1 2
    7 3
    1 1 2 2 1 1 4
    
    Output:
    3
    0
    3
    2
    4
    */
    

      

  • 相关阅读:
    UVALive 7752 Free Figurines (瞎搞)
    ifram的使用 左边是<a>链接 右边是对应网页嵌套的显示网页链接内容 和toggle的收放用法
    java.util.Collections.synchronizedSet()方法的使用
    hibernate的反向生成改懒加载的地方
    SSM的XML和WEB.XML的配置
    通过System获取java环境变量的路径
    Java:对象的强、软、弱和虚引用的区别
    Struts2方法调用的三种方式(有新的!调用方法的说明)
    静态代理,动态代理,Cglib代理详解
    spring自定义注解拦截器的配置
  • 原文地址:https://www.cnblogs.com/wenruo/p/4906333.html
Copyright © 2011-2022 走看看