QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#122525#6539. Treasure BoxScarlett_boyWA 2ms11616kbC++177.2kb2023-07-10 17:46:372023-07-10 17:46:40

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-07-10 17:46:40]
  • 评测
  • 测评结果:WA
  • 用时:2ms
  • 内存:11616kb
  • [2023-07-10 17:46:37]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
#define int long long
int n, c;
char s[N];
int Cost[N];

ll Val[N];

struct Segment_Tree {
    vector<int> tag, Min;
    int Mi = 1, Ma = 1e9;

    Segment_Tree(int M) : tag((M + 1) * 4, 0), Min((M + 1) * 4, 0) { Ma = M; }

    inline void pushup(int &p) {
        Min[p] = min(Min[p << 1], Min[p << 1 | 1]);
    }

    inline void pushdown(int &p, int &l, int &r, int &mid) {
        if (tag[p]) {
            int &W = tag[p];
            Min[p << 1] += W, Min[p << 1 | 1] += W;
            tag[p << 1] += W, tag[p << 1 | 1] += W;
            W = 0;
        }
    }

    inline void add(int p, int l, int r, int x, int y, int w) {
        if (x <= l && r <= y) {
            Min[p] += w;
            tag[p] += w;
            return;
        }
        int mid = l + r >> 1;
        pushdown(p, l, r, mid);
        if (x <= mid) add(p << 1, l, mid, x, y, w);
        if (y > mid) add(p << 1 | 1, mid + 1, r, x, y, w);
        pushup(p);
    }

    inline void add(int x, int y, int w) { add(1, Mi, Ma, x, y, w); }

    inline int query(int p, int l, int r, int x, int y) {
        if (x <= l && r <= y) return Min[p];
        int mid = l + r >> 1, Ans = LLONG_MAX;
        pushdown(p, l, r, mid);
        if (x <= mid) Ans = min(Ans, query(p << 1, l, mid, x, y));
        if (y > mid) Ans = min(Ans, query(p << 1 | 1, mid + 1, r, x, y));
        return Ans;
    }

    inline int query(int l, int r) { return query(1, Mi, Ma, l, r); }

};

ll Ans[N];

void SOLVE() {
    ll Sum = 0;
    for (int i = 1; i <= n / 2; i++) {
        if (s[i] != s[n + 1 - i]) Sum += Cost[i];
    }
    Val[n / 2] = Sum;
    for (int i = n / 2 + 1; i <= n; i++) {
        if (s[i] == s[n - i + 1]) Val[i] = Val[i - 1];
        else {
            Val[i] = Val[i - 1] + min(Cost[i], Cost[n + 1 - i]) - Cost[n + 1 - i];
        }
    }
//    for (int i = n / 2; i <= n; i++) {
//        cout << " " << Val[i] << " ";
//    }
//    cout << "\n";
    Segment_Tree T(n);
    for (int i = n / 2; i <= n; i++) {
//        cout << " " << Val[i] + (i - 1) * c << " \n"[i == n];
        T.add(i, i, Val[i] + (i - 1) * c);
    }
    Ans[1] = min(Ans[1], T.query(n / 2, n));

//    for (int j = n / 2; j <= n; j++) {
//        cout << T.query(j, j) << " \n"[j == n];
//    }
    int Left = n / 2, L = n / 2;
    for (int i = 2; i <= n; i++) {
//        cout << i << ": ";
        if (i > Left) {
            if (n & 1) {
                if (i == Left + 1) {
                    T.add(Left, Left, c);
                    if (i <= n - 2) T.add(i, n - 2, -c);
                    T.add(n, n, c);
                } else {
                    T.add(Left, i - 1, c);
                    T.add(i, n, -c);
                }
            } else {
                if (i == Left + 1) {
                    T.add(Left, Left, c);
                    if (i < n)T.add(i, n - 1, -c);
                } else {
                    T.add(Left, i - 1, c);
                    T.add(i, n, -c);
                }
            }
        } else {
            int R = 2 * i - 1;
            if (R <= Left) {
                T.add(Left, n, c);
            } else {
                T.add(R, n, c);
                if (L % 2 == 0) {
                    if (L > Left) T.add(Left, L - 1, -c);
                } else {
                    T.add(Left, L, -c);
                }
                L = R;
            }
        }
//        for (int j = n / 2; j <= n; j++) {
//            cout << T.query(j, j) << " \n"[j == n];
//        }
        Ans[i] = min(Ans[i], T.query(Left, n));
    }
}

void SOLVE2() {
    reverse(s + 1, s + 1 + n);
    reverse(Cost + 1, Cost + 1 + n);
    ll Sum = 0;
    for (int i = 1; i <= n / 2; i++) {
        if (s[i] != s[n + 1 - i]) Sum += Cost[i];
    }
    Val[n / 2] = Sum;
    for (int i = n / 2 + 1; i <= n; i++) {
        if (s[i] == s[n - i + 1]) Val[i] = Val[i - 1];
        else {
            Val[i] = Val[i - 1] + min(Cost[i], Cost[n + 1 - i]) - Cost[n + 1 - i];
        }
    }
//    for (int i = n / 2; i <= n; i++) {
//        cout << " " << Val[i] << " ";
//    }
//    cout << "\n";
    Segment_Tree T(n);
    for (int i = n / 2; i <= n; i++) {
//        cout << " " << Val[i] + (i - 1) * c << " \n"[i == n];
        T.add(i, i, Val[i] + (i - 1) * c);
    }
    Ans[n] = min(Ans[n], T.query(n / 2, n));

//    for (int j = n / 2; j <= n; j++) {
//        cout << T.query(j, j) << " \n"[j == n];
//    }
    int Left = n / 2, L = n / 2;
    for (int i = 2; i <= n; i++) {
//        cout << i << ": ";
        if (i > Left) {
            if (n & 1) {
                if (i == Left + 1) {
                    T.add(Left, Left, c);
                    if (i <= n - 2) T.add(i, n - 2, -c);
                    T.add(n, n, c);
                } else {
                    T.add(Left, i - 1, c);
                    T.add(i, n, -c);
                }
            } else {
                if (i == Left + 1) {
                    T.add(Left, Left, c);
                    if (i < n)T.add(i, n - 1, -c);
                } else {
                    T.add(Left, i - 1, c);
                    T.add(i, n, -c);
                }
            }
        } else {
            int R = 2 * i - 1;
            if (R <= Left) {
                T.add(Left, n, c);
            } else {
                T.add(R, n, c);
                if (L % 2 == 0) {
                    if (L > Left) T.add(Left, L - 1, -c);
                } else {
                    T.add(Left, L, -c);
                }
                L = R;
            }
        }
//        for (int j = n / 2; j <= n; j++) {
//            cout << T.query(j, j) << " \n"[j == n];
//        }
        Ans[n + 1 - i] = min(Ans[n + 1 - i], T.query(Left, n));
    }
}

char ss[N];
int Z;
int C[N];
int nn;

void init() {
    cin >> nn >> c;
    cin >> (ss + 1);
    for (int i = 1; i <= nn; i++) {
        cin >> C[i];
    }
    int pos = 1;
    for (int i = 1; i <= nn; i++) {
        if (ss[i] != ss[nn - i + 1]) {
            pos = i;
            break;
        }
    }
    Z = pos;
    n = nn - (pos - 1) * 2;
    for (int i = 1; i <= n; i++) {
        s[i] = ss[pos + i - 1];
        Cost[i] = C[pos + i - 1];
    }
}

void solve() {
    init();
    vector<int> vec;
    for (int i = 1; i <= n; i++) {
        if (s[i] != s[n + 1 - i]) {
            vec.push_back(i);
        }
    }
    if (vec.empty()) {
        for (int i = 1; i <= n; i++) cout << 0 << " \n"[i == n];
        return;
    }
    for (int i = 1; i <= n; i++) Ans[i] = LLONG_MAX;
    SOLVE();
    SOLVE2();
    for (int i = 1; i < Z; i++) {
        cout << Ans[1] + (Z - i) * c << " ";
    }
    for (int i = 1; i <= n; i++) cout << Ans[i] << " ";
    for (int i = 1; i < Z; i++) {
        cout << Ans[n] + (i) * c << " ";
    }
    cout << "\n";
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int _ = 1;
    cin >> _;
    for (int o = 1; o <= _; o++) {
        //      cout << "Case #<<" << o << ": ";
        solve();
    }
    return 0;
}

/*

1
5 1
ABCDE
7 1 4 5 1


1
5 1
ABCDA
7 1 4 5 1

*/

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 9512kb

input:

2
5 1
ABCDE
7 1 4 5 1
5 1
ABCDA
7 1 4 5 1

output:

6 5 6 6 5 
2 1 2 3 4 

result:

ok 10 numbers

Test #2:

score: -100
Wrong Answer
time: 2ms
memory: 11616kb

input:

1
10 4
AABABBABAB
10 3 4 10 7 1 8 10 7 6

output:

26 30 34 30 26 22 26 30 26 22 

result:

wrong answer 1st numbers differ - expected: '10', found: '26'