Submission #889883

#TimeUsernameProblemLanguageResultExecution timeMemory
889883boris_mihovCouncil (JOI23_council)C++17
100 / 100
1171 ms541724 KiB
#include <algorithm>
#include <iostream>
#include <numeric>
#include <cassert>
#include <cstring>
#include <vector>
#include <bitset>

typedef long long llong;
const int MAXN = 300000 + 10;
const int MAXB = (1 << 20);
const int MAXM = 21;

int n, m;
int a[MAXN];
int cntMask[MAXB];
llong comb[MAXM][MAXM];
llong up[MAXB][MAXM][2];
llong down[MAXB][MAXM];
llong cntDown[MAXB];
int cnt[MAXB];

int zero, one, two;

void solve()
{
    for (int i = 0 ; i < m ; ++i)
    {
        if (cnt[i] >= n / 2 + 2) two |= (1 << i);
        else if (cnt[i] == n / 2 + 1) one |= (1 << i);
        else if (cnt[i] == n / 2) zero |= (1 << i);
    }

    // std::cout << "zero: " << std::bitset <12> (zero).to_string() << '\n';
    // std::cout << "one : " << std::bitset <12> (one).to_string() << '\n';
    // std::cout << "two : " << std::bitset <12> (two).to_string() << '\n';

    for (int i = 0 ; i <= m ; ++i)
    {   
        comb[i][0] = 1; 
    }

    for (int i = 1 ; i <= m ; ++i)
    {
        for (int j = 1 ; j <= i ; ++j)
        {
            comb[i][j] = comb[i - 1][j] + comb[i - 1][j - 1];
        }
    }

    for (int i = 1 ; i <= n ; ++i)
    {
        // std::cout << "increase: " << std::bitset <12> (((1 << m) - 1) ^ a[i]).to_string() << '\n';
        cntDown[((1 << m) - 1) ^ a[i]]++;
    }

    for (int mask = (1 << m) - 1 ; mask >= 0 ; --mask)
    {
        down[mask][m] = cntDown[mask];
        for (int bit = m - 1 ; bit >= 0 ; --bit)
        {
            if (mask & (1 << bit))
            {
                down[mask][bit] = down[mask][bit + 1];
            } else
            {
                down[mask][bit] = down[mask][bit + 1];
                down[mask][bit] += down[mask | (1 << bit)][bit + 1];
            }
        }
    }

    for (int mask = 0 ; mask < (1 << m) ; ++mask)
    {
        up[mask][0][m & 1] = down[mask][0];
    }

    
    for (int bit = m - 1 ; bit >= 0 ; --bit)
    {
        for (int mask = 0 ; mask < (1 << m) ; ++mask)
        {
            int myPop = __builtin_popcount(mask);
            // if (std::bitset <12> (mask).to_string() == "010001101110") std::cout << "count is: " << std::bitset <12> (mask).to_string() << " (" << myPop << ") = " << down[mask][0] << '\n';
            for (int pop = 0 ; pop <= myPop ; ++pop)
            {  
                up[mask][pop][bit & 1] = 0;
                if (mask & (1 << bit))
                {
                    if (pop > 0) up[mask][pop][bit & 1] += up[mask][pop - 1][(bit & 1) ^ 1];
                    up[mask][pop][bit & 1] += up[mask ^ (1 << bit)][pop][(bit & 1) ^ 1];
                } else
                {
                    up[mask][pop][bit & 1] = up[mask][pop][(bit & 1) ^ 1];
                }
            }
        }
    }

    for (int i = 1 ; i <= n ; ++i)
    {
        int answer = __builtin_popcount(two | (one & (~a[i])));
        int mask = (one & a[i]) | (zero & (~a[i]));
        int myAnd = __builtin_popcount(mask & (~a[i]));
        // std::cout << "answer: " << answer << '\n';
        // std::cout << "mask: " << std::bitset <12> (mask).to_string()  << '\n';
        // std::cout << "curr: " << std::bitset <12> (~a[i]).to_string()  << '\n';
        // std::cout << "and&: " << std::bitset <12> ((~a[i]) & mask).to_string()  << '\n';

        for (int pop = m ; pop >= 0 ; --pop)
        {
            // std::cout << "add?: " << pop << ": " << up[mask][pop][0] << ' ' << comb[myAnd][pop] << '\n';
            if (up[mask][pop][0] > comb[myAnd][pop])
            {
                answer += pop;
                break;
            }
        }

        std::cout << answer << '\n';
    }
}

void input()
{   
    std::cin >> n >> m;
    for (int i = 1 ; i <= n ; ++i)
    {
        for (int bit = m - 1 ; bit >= 0 ; --bit)
        {
            int curr;
            std::cin >> curr;

            a[i] <<= 1;
            a[i] |= curr;
            cnt[bit] += curr;
        }
    }
}

void fastIOI()
{
    std::ios_base :: sync_with_stdio(0);
    std::cout.tie(nullptr);
    std::cin.tie(nullptr);
}

int main()
{
    fastIOI();
    input();
    solve();

    return 0;
}
#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...