제출 #576678

#제출 시각아이디문제언어결과실행 시간메모리
576678MadokaMagicaFan카니발 티켓 (IOI20_tickets)C++14
100 / 100
1036 ms134856 KiB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using vi = vector<int>;
using vll = vector<ll>;
using pi = pair<int,int>;

const ll inf = 1e10;

#define all(v)          v.begin(),v.end()
#define sort(v)         sort(all(v))
#define endl            '\n'
#define forn(i,n)       for(int i = 0; i < n; ++i)
#define forbe(i,b,e)    for(int i = b; i < e; ++i)
#define forr(i,n)       for(int i = n-1; i >= 0; --i)
#define sz(v)           ((int)v.size())
#define pb              push_back
#define f               first
#define s               second

//#define ONTST

const int N = 1505;
const int M = 1505;

void allocate_tickets(vector<vi>s);


using pl = pair<ll,int>;

ll subtaskidk(int k, vector<vi> &x) {
    int n = sz(x);
    int m = sz(x[0]);
    vector<vi> s(n);
    vector<pair<ll,int>> vals;
    forn(i,n) s[i].assign(m,-1);
    vector<vector<pair<ll,int>>> sval(n);

    int topp[N];
    int botp[N];

    forn(i,n) {
        forn(j,m) {
            sval[i].pb({x[i][j], j});
        }
        sort(sval[i]);
    }

    bitset<N*M> c;
    bitset<N*M> z;

    forn(i,n) {
        if (i < (n>>1)) {
            topp[i] = m-1;
            botp[i] = k;
        } else {
            topp[i] = m-1-k;
            botp[i] = 0;
        }
    }

    priority_queue<pl> q1;
    priority_queue<pl, vector<pl>, greater<pl>> q2;
    
    forn(i,n) {
        if (botp[i])    q1.push({sval[i][ botp[i]-1 ].f + sval[i][ topp[i] ].f, i});
        else            q1.push({-inf,i});

        if (topp[i]<m-1)    q2.push({sval[i][ botp[i] ].f + sval[i][ topp[i]+1 ].f, i});
        else                q2.push({inf,i});
    }
    while (sz(q1)) {
        auto u1 = q1.top();
        auto u2 = q2.top();

        if (u1.f <= u2.f)
            break;
        
        --botp[u1.s];
        --topp[u1.s];
        ++botp[u2.s];
        ++topp[u2.s];
        q1.pop();
        q2.pop();

        int i = u1.s;
        if (botp[i])    q1.push({sval[i][ botp[i]-1 ].f + sval[i][ topp[i] ].f, i});
        else            q1.push({-inf,i});

        i = u2.s;
        if (topp[i]<m-1)    q2.push({sval[i][ botp[i] ].f + sval[i][ topp[i]+1 ].f, i});
        else                q2.push({inf,i});
    }

    ll ans = 0;
    forn(i ,n) {
        for(int j = m-1; j > topp[i]; --j) c[ i*m + sval[i][j].s ] = 1;
        for(int j = m-1; j > topp[i]; --j) ans += sval[i][j].f;
        for(int j = 0; j < botp[i]; ++j)  z[ i*m + sval[i][j].s ] = 1;
        for(int j = 0; j < botp[i]; ++j)  ans -= sval[i][j].f;
    }

    forn(i,n) {
        forn(j,m) {
            if (c[ i*m + j ]) {
                vals.pb({x[i][j] * 2 + 1,i * m + j});
            } else {
                vals.pb({x[i][j] * 2,i * m + j});
            }
        }
    }
    sort(vals);

    forn(i,n) {
        topp[i] = m-1;
        botp[i] = 0;
    }

    bitset<N> up;
    bitset<N> us;

    int cnt;
    int ucnt;
    int u = 0;
    int str = 0;
    int ind;

    queue<int> b[N];
    queue<int> t[N];

    int bcnt = 0;
    int rcnt = 0;
    while (u < k) {
        cnt = 0;
        ucnt = 0;
        rcnt = 0;
        forn(i,n) {
            up[i] = 0;
            us[i] = 0;
            if (sz(t[i])) {
                up[i] = 1;
                us[i] = 1;
                ++cnt;
                ++ucnt;
            } else if (sz(b[i])) {
                us[i] = 1;
                ++cnt;
            }
        }
        while (cnt < n || ucnt < (n>>1)) {
            ind = vals[str].s;
            ++str;
            if (c[ ind ]) {
                t[ind/m].push(ind);
                if (!up[ind/m])
                    ++ucnt;
                up[ind/m] = 1;
                if (!us[ind/m]) {
                    us[ind/m] = 1;
                    ++cnt;
                }
            }

            if (z[ ind ]) {
                ++bcnt;
                b[ind/m].push(ind);
                if (!us[ind/m]) {
                    us[ind/m] = 1;
                    ++cnt;
                }
            }
        }
        forn(i,n) {
            if (up[i] && (sz(b[i]) == 0)) {
                s[i][t[i].front()%m] = u;
                t[i].pop();
                ++rcnt;
                us[i] = 0;
            }
        }
        
        forn(i,n) {
            if (!us[i]) continue;
            if (up[i] && rcnt < (n>>1)) {
                s[i][t[i].front()%m] = u;
                t[i].pop();
                ++rcnt;
            } else {
                s[i][b[i].front()%m] = u;
                b[i].pop();
            }
        }

        ++u;
    }

    allocate_tickets(s);

    return ans;
}


ll find_maximum(int k, vector<vi>x) {
    return subtaskidk(k,x);
}

#ifdef ONPC
void allocate_tickets(vector<vi>s) {
    forn(i, sz(s)) {
        forn(j, sz(s[0])) {
            cout << s[i][j] << ' ';
        }
        cout << endl;
    }
}

void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<vi> x(n);
    forn(i,n) {
        x[i].assign(m,0);
    }

    forn(j,m) {
        forn(i,n) {
            cin >> x[i][j];
        }
    }

    cout << find_maximum(k, x) << endl;
}

int main() {
    freopen("input", "r", stdin);
//    ios_base::sync_with_stdio(0);cin.tie(0);
    solve();
}
#endif
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...