답안 #792786

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
792786 2023-07-25T08:44:52 Z 반딧불(#10051) Line Town (CCO23_day1problem3) C++17
0 / 25
2 ms 468 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll INF = 1e18;

struct segTree{
    int tree[1<<20];

    void init(int i, int l, int r){
        tree[i] = 0;
        if(l==r) return;
        int m = (l+r)>>1;
        init(i*2, l, m);
        init(i*2+1, m+1, r);
    }

    void update(int i, int l, int r, int x, int v){
        if(l==r){
            tree[i] = v;
            return;
        }
        int m = (l+r)>>1;
        if(x<=m) update(i*2, l, m, x, v);
        else     update(i*2+1, m+1, r, x, v);
        tree[i] = tree[i*2] + tree[i*2+1];
    }

    int findRight(int i, int l, int r, int x){
        if(r<x || !tree[i]) return r+1;
        if(l==r) return l;
        int m = (l+r)>>1;
        int tmp = findRight(i*2, l, m, x);
        if(tmp == m+1) return findRight(i*2+1, m+1, r, x);
        else return tmp;
    }

    int findLeft(int i, int l, int r, int x){
        if(x<l || !tree[i]) return l-1;
        if(l==r) return l;
        int m = (l+r)>>1;
        int tmp = findLeft(i*2+1, m+1, r, x);
        if(tmp == m) return findLeft(i*2, l, m, x);
        else return tmp;
    }
} tree;

void imp(){
    puts("-1");
    exit(0);
}

int n;
int arr[500002];

void input();
void solve_nozero();
void solve_zero();

int main(){
    input();
    if(count(arr+1, arr+n+1, 0) == 0) solve_nozero();
    else if(count(arr+1, arr+n+1, 0) == n){
        puts("0");
        return 0;
    }
    else solve_zero();
}

void input(){
    scanf("%d", &n);
    for(int i=1; i<=n; i++) scanf("%d", &arr[i]);
    if(n==1){
        puts("0");
        exit(0);
    }

    vector<int> vec;
    for(int i=1; i<=n; i++) if(arr[i]) vec.push_back(abs(arr[i]));
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    for(int i=1; i<=n; i++){
        if(!arr[i]) continue;
        arr[i] = (lower_bound(vec.begin(), vec.end(), abs(arr[i])) - vec.begin() + 1) * (arr[i]<0 ? -1 : 1);
    }

    int odd1 = 0, even1 = 0;
    for(int i=1; i<=n; i++) if(arr[i] == 1){
        if(i%2) odd1++;
        else even1++;
    }

//    if(n%2==0 && !(odd1-even1 == 0 || odd1-even1 == -1)) imp();
//    if(n%2==1 && !(odd1-even1 == 0 || odd1-even1 ==  1)) imp();
//    if(abs(odd1 - even1) > 1) imp();
}

ll ans;
ll prf[500002], suf[500002];

int c[500002];

void flip(int x){
    c[x] = -c[x];
    if(1<x) tree.update(1, 1, n-1, x-1, c[x] == c[x-1]);
    if(x<n) tree.update(1, 1, n-1, x, c[x] == c[x+1]);
}

void solve_nozero(){
    for(int i=0; i<=n+1; i++) prf[i] = suf[i] = INF;
    prf[0] = 0;
    suf[n+1] = 0;
    ll cnt = 0;
    int MX = 0;

    /// prf�� ���Ѵ�
    tree.init(1, 1, n-1);
    for(int i=1; i<=n; i++) c[i] = arr[i];
    for(int i=1; i<n; i++) if(c[i] == c[i+1]) tree.update(1, 1, n-1, i, 1);

    cnt = 0, MX = 0;
    for(int i=1; i<=n; i++){
        if(c[i] == -1){
            if(i >= MX) prf[i] = cnt;
            continue;
        }
//        int j = i+1;
//        while(j<=n && c[j] != c[j-1]) j++;
        int j = tree.findRight(1, 1, n-1, i) + 1;
        if(j>n) break;
        MX = max(MX, j);

        cnt += j-i;
        flip(j), flip(i);
        if(MX<=i+1) prf[++i] = cnt;
    }

    /// suf�� ���Ѵ�
    tree.init(1, 1, n-1);
    for(int i=1; i<=n; i++) c[i] = arr[i];
    for(int i=1; i<n; i++) if(c[i] == c[i+1]) tree.update(1, 1, n-1, i, 1);

    cnt = 0, MX = n+1;
    for(int i=n; i>=1; i--){
        if(c[i] == 1){
            if(i <= MX) suf[i] = cnt;
            continue;
        }
//        int j = i-1;
//        while(j>=1 && c[j] != c[j+1]) j--;
        int j = tree.findLeft(1, 1, n-1, i-1);
        if(j<1) break;
        MX = min(MX, j);

        cnt += i-j;
        flip(j), flip(i);
        if(MX>=i-1) suf[--i] = cnt;
    }

    ans = INF;
    for(int i=0; i<=n; i++) ans = min(ans, prf[i] + suf[i+1]);
    assert(ans != INF);
    printf("%lld", ans == INF ? -1 : ans);
}

ll dist[500002];
ll distA[500002], distB[500002];

void solve_zero(){
    ll cnt = 0;
    int MX, k, loc, S = n - count(arr+1, arr+n+1, 0);
    for(int i=0; i<=S+1; i++) prf[i] = suf[i] = INF;
    prf[0] = 0;
    suf[S+1] = 0;

    { /// dist�� ���ϴ� �κ�
        int cnt = 0;
        for(int i=1; i<=n; i++){
            if(arr[i]) continue;
            cnt++; /// cnt��° 0
            int x = i-cnt+1; /// ���⼭ �̵� �Ÿ��� 0���� �ּ�

            distA[1]--, distB[1] += x;
            distA[x]+=2, distB[x] -= x*2;
        }
        for(int i=1; i<=n; i++){
            distA[i] += distA[i-1], distB[i] += distB[i-1];
            dist[i] = distA[i] * i + distB[i];
        }
    }

    /// �迭 ���ļ� �ű�
    k=0, loc=0;
    for(int i=1; i<=n; i++){
        if(arr[i] == 0) k++;
        else c[++loc] = arr[i] * (k%2 == 0 ? 1 : -1);
    }
    if(S==1) prf[1] = (c[1] == -1 ? 0 : INF);
    else{
        tree.init(1, 1, S-1);
        for(int i=1; i<S; i++) if(c[i] == c[i+1]) tree.update(1, 1, S-1, i, 1);
        cnt = 0, MX = 0;
        for(int i=1; i<=S; i++){
            if(c[i] == -1){
                if(i >= MX) prf[i] = cnt;
                continue;
            }
            int j = tree.findRight(1, 1, S-1, i) + 1;
            if(j>n) break;
            MX = max(MX, j);

            cnt += j-i;
            flip(j), flip(i);
            if(MX<=i+1) prf[++i] = cnt;
        }
    }

    /// �迭 ���ļ� �ű�
    k=0, loc=S;
    for(int i=n; i>=1; i--){
        if(arr[i] == 0) k++;
        else c[loc--] = arr[i] * (k%2 == 0 ? 1 : -1);
    }
    if(S==1) suf[S] = (c[S] == 1 ? 0 : INF);
    else{
        tree.init(1, 1, S-1);
        for(int i=1; i<S; i++) if(c[i] == c[i+1]) tree.update(1, 1, S-1, i, 1);
        cnt = 0, MX = n+1;
        for(int i=S; i>=1; i--){
            if(c[i] == 1){
                if(i <= MX) suf[i] = cnt;
                continue;
            }
            int j = tree.findLeft(1, 1, S-1, i-1);
            if(j<1) break;
            MX = min(MX, j);

            cnt += i-j;
            flip(j), flip(i);
            if(MX>=i-1) suf[--i] = cnt;
        }
    }

    ans = INF;
    for(int i=0; i<=S; i++) ans = min(ans, prf[i] + suf[i+1] + dist[i+1]);
    assert(ans != INF);
    printf("%lld", ans == INF ? -1 : ans);
}

Compilation message

Main.cpp: In function 'void input()':
Main.cpp:72:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   72 |     scanf("%d", &n);
      |     ~~~~~^~~~~~~~~~
Main.cpp:73:34: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   73 |     for(int i=1; i<=n; i++) scanf("%d", &arr[i]);
      |                             ~~~~~^~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 2 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 2 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1 ms 468 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -