zoukankan      html  css  js  c++  java
  • BestCoder Round #91

    传送门:http://acm.hdu.edu.cn/search.php?field=problem&key=BestCoder+Round+%2391&source=1&searchmode=source

    A题:给你n种字母,每种字母有个权值vali,共cnti个,现在让你在里面挑出任意数量的字符,组合成一个字符串,该字符串的权值的计算方式为val1*1+val2*2+……+valn*n,让你输出字符串最大的权值是多少。这题很容易会有一个错误的贪心,就是把val为负的舍去,然后val从小到大选择。事实上负值时可以选的,比如字符1的权值为-1,字符2的权值为2,字符3的权值为3,那么如果我不选字符1,总权值为2*1+3*2=8,小于选了字符1的权值-1*1+2*2+3*3=12,所以这种贪心是错的。正解是先按val对字符排序,很明显,val大的字符如果不选,val小的就一定不会选。也即是,如果字符ch选了,权值比它大的肯定也会选。那假设它选了,总权值就会增加valch+valch+1,valch+2……valn,因此只要判断valch+valch+1,valch+2……valn是不是大于0,就能确定ch到底要不要选了。可以预处理下后缀和,然后直接扫一遍。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <bitset>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    #define in() freopen("data","r",stdin);
    #define out() freopen("ans","w",stdout);
    #define Clear(Q); while (!Q.empty()) Q.pop();
    #define pb push_back
    
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int maxn = 1e5 + 10;
    const int INF = 0x3f3f3f3f;
    pii N[100];
    vector <int> V;
    int sum[maxn];
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--)
        {
            V.clear();
            int n;
            scanf("%d", &n);
            for (int i = 0; i < n; i++)
            {
                scanf("%d%d", &N[i].X, &N[i].Y);
                while (N[i].Y--)
                    V.pb(N[i].X);
            }
            sort(V.begin(), V.end());
            sum[V.size()] = 0;
            for (int i = V.size() - 1; i >= 0; i--)
                sum[i] = sum[i+1] + V[i];
            ll ans = 0, k = 1;
            for (int i = 0; i < V.size(); i++)
                if (V[i] >= 0 || V[i] + sum[i+1] >= 0)
                {
                    ans += k * V[i];
                    k++;
                }
            printf("%I64d
    ", ans);
        }
        return 0;
    }
    View Code

    B题:有n种植物,每种植物有个适宜温度区间,如果温度适宜,它可以提供ai的研究价值,如果温度大于适宜温度的上限,它可以提供bi的研究价值,如果温度小于适宜温度的下限,它可以提供ci的研究价值。现在让你找到一个温度,使得总研究价值最大,温度可以为任意实数。输出最大总研究价值。先离散化一下温度,然后线段树维护下最大研究价值。注意由于温度是实数,所以离散的时候要,两个数之间要多加一个空位,用于浮点数的统计。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <bitset>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    #define in() freopen("data","r",stdin);
    #define out() freopen("ans","w",stdout);
    #define Clear(Q); while (!Q.empty()) Q.pop();
    #define pb push_back
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int maxn = 2e5 + 10;
    const int inf = 0x3f3f3f3f;
    struct node1
    {
        int l, r, a, b, c;
    } N[maxn];
    vector<pii> V;
    LL add[maxn<<2];
    LL Max[maxn<<2];
    void PushUp(int rt)
    {
        Max[rt] = max(Max[rt<<1] , Max[rt<<1|1]);
    }
    void PushDown(int rt, int m)
    {
        if (add[rt])
        {
            add[rt<<1] += add[rt];
            add[rt<<1|1] += add[rt];
            Max[rt<<1] += add[rt];
            Max[rt<<1|1] += add[rt];
            add[rt] = 0;
        }
    }
    
    void update(int L, int R, int c, int l, int r, int rt)
    {
        if (L <= l && r <= R)
        {
            add[rt] += c;
            Max[rt] += c;
            return ;
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        if (L <= m) update(L , R , c , lson);
        if (m < R) update(L , R , c , rson);
        PushUp(rt);
    }
    LL query(int L, int R, int l, int r, int rt)
    {
        if (L <= l && r <= R)
        {
            return Max[rt];
        }
        PushDown(rt , r - l + 1);
        int m = (l + r) >> 1;
        LL ret = 0;
        if (L <= m) ret = max(ret, query(L , R , lson));
        if (m < R) ret = max(ret, query(L , R , rson));
        return ret;
    }
    
    void init()
    {
        V.clear();
        clr(add, 0);
        clr(Max, 0);
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--)
        {
            init();
            V.pb(make_pair(0,-1));
            int n;
            scanf("%d", &n);
            for (int i = 0; i < n; i++)
            {
                scanf("%d%d%d%d%d", &N[i].l, &N[i].r, &N[i].a, &N[i].b, &N[i].c);
                V.pb(make_pair(2 * N[i].l , i));
                V.pb(make_pair(2 * N[i].r , i));
                V.pb(make_pair(2 * N[i].l + 1, -1));
                V.pb(make_pair(2 * N[i].r + 1, -1));
                N[i].l = N[i].r = -1;
            }
            int pos = 1;
            sort(V.begin(), V.end());
            for (int i = 0; i < V.size(); i++)
            {
                if (V[i].Y == -1)
                {
                    pos++;
                    continue;
                }
                if (N[V[i].Y].l == -1)
                    N[V[i].Y].l = pos;
                else N[V[i].Y].r = pos;
                if (i != V.size() - 1 && V[i].X == V[i+1].X) continue;
                pos++;
            }
            pos--;
            for (int i = 0; i < n; i++)
            {
                if (N[i].l - 1 >= 1) update(1, N[i].l - 1, N[i].c, 1, pos, 1);
                update(N[i].l, N[i].r, N[i].a, 1, pos, 1);
                if (N[i].r + 1 <= pos) update(N[i].r + 1, pos, N[i].b, 1, pos, 1);
            }
            printf("%I64d
    ", query(1, pos, 1, pos, 1));
        }
        return 0;
    }
    View Code

    剩下两题不会了= =,这场能升分得益于A题的错误贪心发现得早。。没造成太多罚时损失,遗憾是手速太慢没hack到人。B题知道做法,但是调线段树调了半天,还没注意到可以是实数,样例一直调不过,决定去刷下线段树专题,,补补线段树。

    2017-01-23 22:09:00

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • 相关阅读:
    052 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 14 Eclipse下程序调试——debug2 多断点调试程序
    051 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 13 Eclipse下程序调试——debug入门1
    050 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 12 continue语句
    049 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 11 break语句
    048 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 10 案例——阶乘的累加和
    047 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 09 嵌套while循环应用
    046 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 08 for循环的注意事项
    045 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 07 for循环应用及局部变量作用范围
    剑指OFFER----面试题04.二维数组中的查找
    剑指OFFER----面试题03. 数组中重复的数字
  • 原文地址:https://www.cnblogs.com/scaugsh/p/6339179.html
Copyright © 2011-2022 走看看