2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)

2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)(2020.5.31)

昨晚修仙,今天这场确实打到一半就打不动了。反正也是一人一队,干脆后半场摸鱼。

所以最后就搞了三道水题(哭

A、Concerts

就是这题做了我半天。

一开始感觉 O ( n k ) O(nk) 1 e 7 1e7 可能过不了,不过大哥说0.3s能过,然后我就大胆写了。

这题考虑一个 d p dp ,设长度为 k k 的串为 a a ,另一个为 b b d p [ i ] [ j ] dp[i][j] a a 串前 i i 个与 b b 串前 j j 个匹配所得到的结果,那么有 d p [ i ] [ j ] = { d p [ i ] [ j 1 ] , a [ i ] ! = b [ j ] d p [ i ] [ j 1 ] + d p [ i 1 ] [ j h [ a [ i 2 ] A ] 1 ] , a [ i ] = = b [ j ] dp[i][j]=\begin{cases} dp[i][j-1], a[i]!=b[j]\\ dp[i][j-1]+dp[i-1][j-h[a[i-2]-'A']-1], a[i]==b[j] \end{cases}

其中 h [ i ] h[i] 记录的是距离的时间。

这方程很好推,本来应该最多半小时切掉的,结果没想到这坑爹题目上面的数据范围是 n , k n,k 这么给的,下面输入是 k , n k,n 这么给的。看反之后找了半天问题。

另外就是好不容易写好了一直WA3,后来群里说是题目数据错了…结果为了加大空间还搞了个滚动数组。

打完返回Problems面板才发现下面写了个数据错误的公告。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7 + 10, MAXK = 1e7 + 10;
const int MOD = 1e9 + 7;
int main()
{
    int n, k; cin >> k >> n;
    static int dp[2][MAXN];
    dp[0][0] = dp[1][0] = 0;
    int h[26];
    for (int i = 0; i < 26; ++i) scanf("%d", h + i);
    string a, b; cin >> a >> b;
    for (int i = 1; i <= n; ++i)
    {
        dp[1][i] = dp[1][i - 1];
        if (a[0] == b[i - 1]) ++dp[1][i];
    }
    int cnt = 1;
    for (int i = 2; i <= k; ++i)
    {
        cnt ^= 1;
        for (int j = 1; j <= n; ++j)
        {
            dp[cnt][j] = dp[cnt][j - 1];
            if (a[i - 1] == b[j - 1])
            {
                if (j - h[a[i - 2] - 'A'] - 1 >= 0)
                    dp[cnt][j] = (dp[cnt][j] + dp[cnt ^ 1][j - h[a[i - 2] - 'A'] - 1]) % MOD;
            }
        }
    }
    /*for (int i = 1; i <= k; ++i)
    {
        for (int j = 1; j <= n; ++j)
            cout << dp[i][j] << ' ';
        cout << endl;
    }*/
    cout << dp[cnt][n] << endl;
    return 0;
}

本来之后想做个D,结果交上去一直WA。想了半天算法没问题,可能是我理解错了。

G、Robots

物理题,算一算就好了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e4 + 10;
struct node
{
    int a, t;
};
bool cmp(node a, node b)
{
    return a.a > b.a;
}
int main()
{
    int n; cin >> n;
    node a[MAXN];
    for (int i = 1; i <= n; ++i) scanf("%d%d", &a[i].a, &a[i].t);
    int v = 0; double x0 = 0, x1 = 0;
    for (int i = 1; i <= n; ++i)
    {
        x0 += v * a[i].t + a[i].a * a[i].t * a[i].t / 2.0;
        v += a[i].a * a[i].t;
    }
    v = 0;
    sort(a + 1, a + 1 + n, cmp);
    for (int i = 1; i <= n; ++i)
    {
        x1 += v * a[i].t + a[i].a * a[i].t * a[i].t / 2.0;
        v += a[i].a * a[i].t;
    }
    printf("%.1f\n", x1 - x0);
    return 0;
}

K、Escape Room

这题也卡了我好久。一开始的想法是去找还没用过的数字里第 a [ i ] a[i] 大的数,但是这 O ( n 2 ) O(n^2) 铁超。后来用个玄学排序过了。大概就是越长数字越小,然后长度相同的把后面的赋成更小的值。(因为如果后面比前面大可能会和前面矛盾)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
struct node
{
    int index, len, v;
};
bool cmp1(node a, node b)
{
    if (a.len == b.len) return a.index > b.index;
    else return a.len > b.len;
}
bool cmp2(node a, node b)
{
    return a.index < b.index;
}
int main()
{
    int n; cin >> n;
    node a[MAXN];
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i].len);
        a[i].index = i;
    }
    sort(a + 1, a + 1 + n, cmp1);
    for (int i = 1; i <= n; ++i) a[i].v = i;
    sort(a + 1, a + 1 + n, cmp2);
    for (int i = 1; i <= n; ++i) cout << a[i].v << ' ';
    cout << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36000896/article/details/106458394