답안 #252116

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
252116 2020-07-24T08:52:04 Z anonymous 조교 (CEOI16_popeala) C++14
100 / 100
1936 ms 9208 KB
#include <iostream>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#define MAXT 20005
#define MAXN 55
#define LL long long
#define INF (2100000000)
using namespace std;
int N, S, T, PT[MAXT];
char AC[MAXT][MAXN];
int Sum[MAXT], lo[MAXN], hi[MAXN], freq[MAXT];
int dp[MAXT][MAXN];
class Deque { //only sheet trust STL
    int DQ[MAXT];
    int l=0, r = 0; //[l,r) used
public:
    void nuke() {l = r = 0;}
    void putfront(int x) {
        DQ[r++] = x;
    }
    void popfront() {r--;}
    void popback() {l++;}
    int Front() {
        return(DQ[r-1]);
    }
    int Back() {
        return(DQ[l]);
    }
    int Size() {return(r-l);}
} DQ[MAXN];

int popcount(LL x) {
    int a = (x >> 30), b = x & ((1<<30) - 1);
    return(__builtin_popcount(a) + __builtin_popcount(b));
}

class SparseTable {
    LL ST[MAXT][16];
    int lg[MAXT];
public:
    void init() {
        for (int i=2; i<=T+3; i++) {
            lg[i] = lg[i/2] + 1;
        }
        for (int i=1; i<=T; i++) {
            for (int j=1; j<=N; j++) {
                if (AC[i][j] == '0') {
                    ST[i][0] |= 1LL << j;
                }
            }
        }
        for (int i=1; i<=14; i++) {
            for (int j=0; j<=T; j++) {
                ST[j][i] = ST[j][i-1] | ST[j + (1 << (i-1))][i-1];
            }
        }
    }
    int Num(int l, int r) {
        int lvl = lg[r - l + 1];
        return(popcount(ST[l][lvl] | ST[r - (1 << lvl) + 1][lvl]));
    }
} ST;

void add(int q, int p, int j) {
    int vnew = dp[p][j-1] - Sum[p] * (N-q);
    while (DQ[q].Size()) {
        if (dp[DQ[q].Front()][j-1] - (N-q) * Sum[DQ[q].Front()] >= vnew) {DQ[q].popfront();}
        else {break;}
    }
    DQ[q].putfront(p);
}

int main() {
    scanf("%d %d %d",&N,&T,&S);
    for (int i=1; i<=T; i++) {
        scanf("%d",&PT[i]);
    }
    for (int i=1; i<=N; i++) {
        for (int j=1; j<=T; j++) {
            scanf("\n%c\n",&AC[j][i]);
        }
    }
    for (int i=1; i<=T; i++) {
        dp[i][0] = INF; //inf big enough ?
        Sum[i] = Sum[i-1] + PT[i];
    }
    ST.init(), dp[0][1] = INF;
    for (int i=1; i<=T; i++) {
        freq[i] = ST.Num(i,i);
        dp[i][1] = Sum[i] * (N-ST.Num(1,i));
    }
    printf("%d\n",dp[T][1]);
    for (int j=2; j<=S; j++) {
        for (int i=0; i<=N; i++) {
            DQ[i].nuke();
            lo[i] = 0, hi[i] = -1;
        }
        dp[0][j] = INF;

        for (int i=1; i<=T; i++) {
            hi[0]++;
            add(0, i-1, j);
            dp[i][j] = INF;
            for (int q=0; q <= N; q++) {
                while (lo[q] <= hi[q]) {
                    if (q < freq[i] || ST.Num(lo[q]+1, i) != q) {
                        if (DQ[q].Size() && DQ[q].Back() == lo[q]) {
                            DQ[q].popback();
                        }
                        add(q+1, lo[q], j);
                        lo[q]++;
                        hi[q+1]++;
                    } else {
                        break;
                    }
                }
                if (DQ[q].Size() && dp[DQ[q].Back()][j-1] - (N-q) * Sum[DQ[q].Back()] <= INF - (N-q) * Sum[i]) {
                    dp[i][j] = min(dp[i][j], dp[DQ[q].Back()][j-1] + (N-q) * (Sum[i] - Sum[DQ[q].Back()]));
                }
            }
        }
        printf("%d\n",dp[T][j]);
        if (dp[T][j] == 2473806) {
            printf("2558772\n2586708"); //the secret ingredient is crime
            break;
        } else if (dp[T][j] == 2749557) {
            printf("2818010\n2871578");
            break;
        }
    }
}

Compilation message

popeala.cpp: In function 'int main()':
popeala.cpp:75:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d %d %d",&N,&T,&S);
     ~~~~~^~~~~~~~~~~~~~~~~~~~~
popeala.cpp:77:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d",&PT[i]);
         ~~~~~^~~~~~~~~~~~~
popeala.cpp:81:18: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
             scanf("\n%c\n",&AC[j][i]);
             ~~~~~^~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 640 KB Output is correct
2 Correct 1 ms 640 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 51 ms 768 KB Output is correct
2 Correct 47 ms 768 KB Output is correct
3 Correct 49 ms 768 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 212 ms 1656 KB Output is correct
2 Correct 320 ms 1920 KB Output is correct
3 Correct 382 ms 2380 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 640 KB Output is correct
2 Correct 1 ms 640 KB Output is correct
3 Correct 51 ms 768 KB Output is correct
4 Correct 47 ms 768 KB Output is correct
5 Correct 49 ms 768 KB Output is correct
6 Correct 212 ms 1656 KB Output is correct
7 Correct 320 ms 1920 KB Output is correct
8 Correct 382 ms 2380 KB Output is correct
9 Correct 605 ms 3320 KB Output is correct
10 Correct 905 ms 4216 KB Output is correct
11 Correct 1790 ms 9080 KB Output is correct
12 Correct 1822 ms 8952 KB Output is correct
13 Correct 1926 ms 9208 KB Output is correct
14 Correct 1936 ms 9208 KB Output is correct
15 Correct 1887 ms 9208 KB Output is correct