AtCoder Beginner Contest 163

题目链接

D:
看样例+分析得知,假设现在要选\(i\)个,那么能达到的最大的值就是\(sum_{i_1}=\sum^{n}_{x=n-i+1}{x}\), 最小值就是\(sum_{i_2}=\sum^{i-1}_{x=0}{x}\),那么每次可选择的数量就是\(sum_1-sum_2+1\),那么答案就为\(\sum_{i=k}^{n+1}({sum_{i_1}-sum_{i_2} + 1})\)

#include<bits/stdc++.h>
using namespace std;
#define ms(x,y) memset(x, y, sizeof(x))
#define lowbit(x) ((x)&(-x))
#define sqr(x) ((x)*(x))
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const LL MOD = 1e9+7;

void run_case() {
    int n, k;
    cin >> n >> k;
    LL ans = 0;
    for(int i = k; i <= n+1; ++i) {
        LL t1 = 1LL*(i-1)*i/2;
        LL t2 = 1LL*(n+n-i+1)*i/2;
        (ans += t2 - t1 + 1) %= MOD;
    }
    cout << ans;
}


int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cout.flags(ios::fixed);cout.precision(9);
    //int t; cin >> t;
    //while(t--)
    run_case();
    cout.flush();
    return 0;
}

E:
一开始用贪心做,将\(A_i\)从大到小排序,每次都放在端点,但是样例2、3单纯用该策略是不行的,样例3中,若选用贪心策略,得:
\(111556\),但是使得最大值的方法为: \(611155\), 第二种方法时\(6\)就不是最优,所以应该根据数据范围想到该题为DP问题,但是放的策略肯定也是放在两端为最优,那么可以放在某个区间的两端,可以联想到区间dp
设\(dp_{i,j}\)为闭区间\([i,j]\)还未被选择时,已经选择的最优答案,得到状态转移:
\(dp_{i,j} = max(dp_{i,j+1}+A_k*|j+1-pos_k|, dp_{i-1, j}+A_k*|i-1-pos_k|), k = n-(j-i+1)\),\(k\)表示当前选择是第几个
最终答案就是\(max(dp_{i,i-1}), i\in [1, n]\)

#include<bits/stdc++.h>
using namespace std;
#define ms(x,y) memset(x, y, sizeof(x))
#define lowbit(x) ((x)&(-x))
#define sqr(x) ((x)*(x))
typedef long long LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;



void run_case() {
    int n; cin >> n;
    vector<pll> a;
    for(int i = 1; i <= n; ++i) {
        LL t; cin >> t;
        a.emplace_back(t, 1LL*i);
    }
    sort(a.begin(), a.end(), [&](pll a, pll b) {
        return a.first > b.first;
    });
    vector<vector<LL>> dp(n+2, vector<LL>(n+2));
    for(int i = 1; i <= n; ++i) {
        for(int j = 0; j <= i; ++j) {   // len = r - l + 1, len = n - i
            int l = j+1, r = n - i + l - 1;
            if(r+1<=n) dp[l][r] = max(dp[l][r], dp[l][r+1]+abs(r+1-a[i-1].second)*a[i-1].first);
            if(l-1>=1) dp[l][r] = max(dp[l][r], dp[l-1][r]+abs(l-1-a[i-1].second)*a[i-1].first);
        }
    }
    LL ans = 0;
    for(int i = 1; i <= n; ++i) ans = max(ans, dp[i][i-1]);
    cout << ans;
}


int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cout.flags(ios::fixed);cout.precision(9);
    //int t; cin >> t;
    //while(t--)
    run_case();
    cout.flush();
    return 0;
}

F:
我先放个坑在这里

上一篇:Java Applet无法正常工作


下一篇:AtCoder Beginner Contest 172 C-D