zoukankan      html  css  js  c++  java
  • codeforces 935E 建树,dp

    E. Fafa and Ancient Mathematics

    题意:
    给出一串加减表达式,括号可以互相匹配。其中有 p 个加号, m 个减号,问最后的结果最大可能是多少。 min(p,m)<=100
    tags:
    题目数据范围给了提示。。
    先按括号匹配建好树,dp1[i][j], dp2[i][j] 表示结点 i 子树下面有 j 个数量较小符号的最大最小值,然后在 dfs 的过程中更新即可。

    
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 10005, M = 1e5+10;
    
    int n, m, a[N], cnt[M], tot, tr[M][2];
    ll  dp1[M][105], dp2[M][105];
    bool flag;
    int mn;
    char s[N];
    stack< int > Stack;
    void pushup(int ro) {
        int lson = tr[ro][0], rson = tr[ro][1];
        if(!flag)
        {
            rep(i,0,cnt[ro])
                for(int j=0; j<=cnt[lson] && j<=i; ++j)
                    if(i-j<=cnt[rson])
            {
                dp1[ro][i] = max(dp1[ro][i], dp1[lson][j]+dp1[rson][i-j]);
                dp2[ro][i] = min(dp2[ro][i], dp2[lson][j]+dp2[rson][i-j]);
            }
            rep(i,0,cnt[ro]-1)
                for(int j=0; j<=cnt[lson] && j<=i; ++j)
                    if(i-j<=cnt[rson])
            {
                dp1[ro][i+1] = max(dp1[ro][i+1], dp1[lson][j]-dp2[rson][i-j]);
                dp2[ro][i+1] = min(dp2[ro][i+1], dp2[lson][j]-dp1[rson][i-j]);
            }
        }
        else
        {
            rep(i,0,cnt[ro])
                for(int j=0; j<=cnt[lson] && j<=i; ++j)
                    if(i-j<=cnt[rson])
            {
                dp1[ro][i] = max(dp1[ro][i], dp1[lson][j]-dp2[rson][i-j]);
                dp2[ro][i] = min(dp2[ro][i], dp2[lson][j]-dp1[rson][i-j]);
            }
            rep(i,0,cnt[ro]-1)
                for(int j=0; j<=cnt[lson] && j<=i; ++j)
                    if(i-j<=cnt[rson])
            {
                dp1[ro][i+1] = max(dp1[ro][i+1], dp1[lson][j]+dp1[rson][i-j]);
                dp2[ro][i+1] = min(dp2[ro][i+1], dp2[lson][j]+dp2[rson][i-j]);
            }
        }
    }
    void solve(int ro, int l, int r)
    {
        if('1'<=s[l] && s[l]<='9') return ;
        solve(tr[ro][0], l+1, a[l+1]);
        solve(tr[ro][1], a[r-1], r-1);
        pushup(ro);
    }
    void build(int ro, int l, int r)
    {
        if('1'<=s[l] && s[l]<='9') {
            dp1[ro][0] = dp2[ro][0] = s[l]-'0';
            return ;
        }
        tr[ro][0]=++tot, tr[ro][1]=++tot;
        build(tr[ro][0], l+1, a[l+1]);
        build(tr[ro][1], a[r-1], r-1);
        cnt[ro] = min(mn, cnt[tr[ro][0]]+cnt[tr[ro][1]]+1);
    }
    void Init() {
        rep(i,0,M-1) rep(j,0,104)
            dp1[i][j]=-1e18, dp2[i][j]=1e18;
        mes(cnt, 0);
        tot = 1;
    }
    int main()
    {
        Init();
        scanf("%s", s+1);
        int len = strlen(s+1);
        scanf("%d%d", &n, &m);
        mn = min(n, m);
        if(n < m) flag = true;  //  false -----
        rep(i,1,len)
        {
            if(s[i]=='(') {
                Stack.push(i);
            }
            else if(s[i]==')') {
                int u = Stack.top(); Stack.pop();
                a[u] = i, a[i] = u;
            }
            else if('1'<=s[i] && s[i]<='9') {
                a[i] = i;
            }
        }
        build(1, 1, len);
        solve(1, 1, len);
        printf("%lld
    ", dp1[1][mn]);
    
        return 0;
    }
    
    
  • 相关阅读:
    LIS例题
    基数排序板子
    lower_bound和upper_bound在刷leetcode的时候...
    leetcode1081/316 求字典序最小的包含所有出现字符一次的子序列
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合 【深度优先搜索】【原创】
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合【原创】
    Spring 中注入 properties 中的值
    Java 枚举活用
    Intellij IDEA 快捷键整理(TonyCody)
    WIN API -- 2.Hello World
  • 原文地址:https://www.cnblogs.com/sbfhy/p/8597262.html
Copyright © 2011-2022 走看看