QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#618556#9449. New School Termucup-team4479RE 1ms9924kbC++2319.6kb2024-10-06 23:40:102024-10-06 23:40:10

Judging History

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

  • [2024-10-06 23:40:10]
  • 评测
  • 测评结果:RE
  • 用时:1ms
  • 内存:9924kb
  • [2024-10-06 23:40:10]
  • 提交

answer

#include<bits/stdc++.h>
using namespace std;
constexpr int W = 64;
class Bitset {
private:
    vector<unsigned long long> a;
    int numBits;

    int highBit(unsigned long long x) const {
        return W - 1 - __builtin_clzll(x);
    }

    int lowBit(unsigned long long x) const {
        return __builtin_ffsll(x) - 1;
    }

public:
    Bitset(int size) : a((size + W - 1) / W, 0), numBits(size) {}

    // Copy constructor
    Bitset(const Bitset& other) : a(other.a), numBits(other.numBits) {}

    // Copy assignment operator
    Bitset& operator=(const Bitset& other) {
        if (this != &other) {
            a = other.a;
            numBits = other.numBits;
        }
        return *this;
    }

    // Move constructor
    Bitset(Bitset&& other) noexcept : a(std::move(other.a)), numBits(other.numBits) {
        other.numBits = 0;
    }

    void applyShiftLeft(int shift, int start, int end) {
        if (shift == 0) return;

        int startBlock = start / W;
        int endBlock = (end - 1) / W;
        int startOffset = start % W;
        int endOffset = (end - 1) % W + 1;

        if (shift >= end - start) {
            for (int i = startBlock; i <= endBlock; ++i) {
                a[i] &= ~(((1ull << (min(endOffset, W) - (i == startBlock ? startOffset : 0))) - 1) << (i == startBlock ? startOffset : 0));
            }
            return;
        }

        int blockShift = shift / W;
        int bitShift = shift % W;

        for (int i = endBlock; i >= startBlock; --i) {
            unsigned long long newValue = 0;
            if (i - blockShift >= startBlock) {
                newValue |= (a[i - blockShift] << bitShift);
                if (bitShift && i - blockShift - 1 >= startBlock) {
                    newValue |= (a[i - blockShift - 1] >> (W - bitShift));
                }
            }
            if (i == startBlock) {
                newValue &= (((1ull << (min(endOffset, W) - startOffset)) - 1) << startOffset);
            }
            a[i] &= ~(((1ull << (min(endOffset, W) - (i == startBlock ? startOffset : 0))) - 1) << (i == startBlock ? startOffset : 0));
            a[i] |= newValue;
        }
    }

    void applyShiftRight(int shift, int start, int end) {
        if (shift == 0) return;

        int startBlock = start / W;
        int endBlock = (end - 1) / W;
        int startOffset = start % W;
        int endOffset = (end - 1) % W + 1;

        if (shift >= end - start) {
            for (int i = startBlock; i <= endBlock; ++i) {
                a[i] &= ~(((1ull << (min(endOffset, W) - (i == startBlock ? startOffset : 0))) - 1) << (i == startBlock ? startOffset : 0));
            }
            return;
        }

        int blockShift = shift / W;
        int bitShift = shift % W;

        for (int i = startBlock; i <= endBlock; ++i) {
            unsigned long long newValue = 0;
            if (i + blockShift <= endBlock) {
                newValue |= (a[i + blockShift] >> bitShift);
                if (bitShift && i + blockShift + 1 <= endBlock) {
                    newValue |= (a[i + blockShift + 1] << (W - bitShift));
                }
            }
            if (i == startBlock) {
                newValue &= (((1ull << (min(endOffset, W) - startOffset)) - 1) << startOffset);
            }
            a[i] &= ~(((1ull << (min(endOffset, W) - (i == startBlock ? startOffset : 0))) - 1) << (i == startBlock ? startOffset : 0));
            a[i] |= newValue;
        }
    }

    // Move assignment operator
    Bitset& operator=(Bitset&& other) noexcept {
        if (this != &other) {
            a = std::move(other.a);
            numBits = other.numBits;
            other.numBits = 0;
        }
        return *this;
    }

    // 支持 << 区间
    Bitset operator<<(int shift) const {
        Bitset res = *this;
        res <<= shift;
        return res;
    }

    // 支持 >> 区间
    Bitset operator>>(int shift) const {
        Bitset res = *this;
        res >>= shift;
        return res;
    }

    // 支持 <<=
    Bitset& operator<<=(int shift) {
        if (shift >= numBits) {
            fill(a.begin(), a.end(), 0);
            return *this;
        }

        applyShiftLeft(shift, 0, numBits);
        return *this;
    }

    // 支持 >>=
    Bitset& operator>>=(int shift) {
        if (shift >= numBits) {
            fill(a.begin(), a.end(), 0);
            return *this;
        }

        applyShiftRight(shift, 0, numBits);
        return *this;
    }

    // 支持 []
    bool operator[](int index) const {
        if (index < 0 || index >= numBits) {
            throw out_of_range("Index out of range");
        }
        int blockIndex = index / W;
        int bitIndex = index % W;
        return (a[blockIndex] >> bitIndex) & 1;
    }

    // 支持从高到低的第一个置位
    int highestSetBit() const {
        for (int i = a.size() - 1; i >= 0; --i) {
            if (a[i] != 0) {
                return min(i * W + highBit(a[i]), numBits - 1);
            }
        }
        return -1;
    }

    // 支持从高到低的下一个置位
    int nextHighestSetBit(int index) const {
        if (index < 0 || index >= numBits) {
            return -1;
        }
        int blockIndex = index / W;
        int bitIndex = index % W;
        unsigned long long mask;
        if (bitIndex == 0) {
            mask = 0;
        } else {
            mask = (1ull << bitIndex) - 1;
        }
        if ((a[blockIndex] & mask) != 0) {
            return blockIndex * W + highBit(a[blockIndex] & mask);
        }

        for (int i = blockIndex - 1; i >= 0; --i) {
            if (a[i] != 0) {
                return i * W + highBit(a[i]);
            }
        }

        return -1;
    }

    // 支持从低到高的第一个置位
    int lowestSetBit() const {
        for (int i = 0; i < a.size(); ++i) {
            if (a[i] != 0) {
                return min(i * W + lowBit(a[i]), numBits - 1);
            }
        }
        return -1;
    }

    // 支持从低到高的下一个置位
    int nextLowestSetBit(int index) const {
        if (index < 0 || index >= numBits) {
            return -1;
        }
        int blockIndex = index / W;
        int bitIndex = index % W;
        unsigned long long mask;
        if (bitIndex == W - 1) {
            mask = 0;
        } else {
            mask = ~((1ull << (bitIndex + 1)) - 1);
        }
        if ((a[blockIndex] & mask) != 0) {
            return blockIndex * W + lowBit(a[blockIndex] & mask);
        }

        for (int i = blockIndex + 1; i < a.size(); ++i) {
            if (a[i] != 0) {
                return i * W + lowBit(a[i]);
            }
        }

        return -1;
    }

    // 支持 count
    int count() const {
        int cnt = 0;
        for (auto block : a) {
            cnt += __builtin_popcountll(block);
        }
        return cnt;
    }

    // 支持 any
    bool any() const {
        for (auto block : a) {
            if (block != 0) {
                return true;
            }
        }
        return false;
    }

    // 支持 none
    bool none() const {
        return !any();
    }

    // 支持 all
    bool all() const {
        for (int i = 0; i < numBits; ++i) {
            if (!(*this)[i]) {
                return false;
            }
        }
        return true;
    }

    // 支持 flip
    void flip() {
        for (auto& block : a) {
            block = ~block;
        }
        // Make sure no bits beyond numBits are set
        if (numBits % W != 0) {
            a.back() &= (1ull << (numBits % W)) - 1;
        }
    }

    // 支持 flip(int index)
    void flip(int index) {
        if (index < 0 || index >= numBits) {
            throw out_of_range("Index out of range");
        }
        int blockIndex = index / W;
        int bitIndex = index % W;
        a[blockIndex] ^= (1ull << bitIndex);
    }

    // 支持 set(int index)
    void set(int index) {
        if (index < 0 || index >= numBits) {
            throw out_of_range("Index out of range");
        }
        int blockIndex = index / W;
        int bitIndex = index % W;
        a[blockIndex] |= (1ull << bitIndex);
    }

    // 支持 set(int index, bool value)
    void set(int index, bool value) {
        if (value) {
            set(index);
        } else {
            reset(index);
        }
    }

    // 支持 set()
    void set() {
        for (auto& block : a) {
            block = ~0ull;
        }
        // Make sure no bits beyond numBits are set
        if (numBits % W != 0) {
            a.back() &= (1ull << (numBits % W)) - 1;
        }
    }

    // 支持 reset(int index)
    void reset(int index) {
        if (index < 0 || index >= numBits) {
            throw out_of_range("Index out of range");
        }
        int blockIndex = index / W;
        int bitIndex = index % W;
        a[blockIndex] &= ~(1ull << bitIndex);
    }

    // 支持 reset()
    void reset() {
        fill(a.begin(), a.end(), 0);
    }

    // 支持 |=
    Bitset& operator|=(const Bitset& other) {
        if (numBits != other.numBits) {
            throw invalid_argument("Bitsets must be of the same size");
        }
        for (int i = 0; i < a.size(); ++i) {
            a[i] |= other.a[i];
        }
        return *this;
    }

    // 支持 |
    Bitset operator|(const Bitset& other) const {
        Bitset res = *this;
        res |= other;
        return res;
    }

    // 支持 &=
    Bitset& operator&=(const Bitset& other) {
        if (numBits != other.numBits) {
            throw invalid_argument("Bitsets must be of the same size");
        }
        for (int i = 0; i < a.size(); ++i) {
            a[i] &= other.a[i];
        }
        return *this;
    }

    // 支持 &
    Bitset operator&(const Bitset& other) const {
        Bitset res = *this;
        res &= other;
        return res;
    }

    // 支持 ^=
    Bitset& operator^=(const Bitset& other) {
        if (numBits != other.numBits) {
            throw invalid_argument("Bitsets must be of the same size");
        }
        for (int i = 0; i < a.size(); ++i) {
            a[i] ^= other.a[i];
        }
        return *this;
    }

    // 支持 ^
    Bitset operator^(const Bitset& other) const {
        Bitset res = *this;
        res ^= other;
        return res;
    }

    // 支持 ~
    Bitset operator~() const {
        Bitset res = *this;
        for (int i = 0; i < a.size(); ++i) {
            res.a[i] = ~a[i];
        }
        if (numBits % W != 0) {
            res.a.back() &= (1ull << (numBits % W)) - 1;
        }
        return res;
    }

    // 支持 size
    int size() const {
        return numBits;
    }

    // 支持 test
    bool test(int index) const {
        return (*this)[index];
    }

    // 支持 to_ullong
    unsigned long long to_ullong() const {
        if (numBits > W) {
            throw overflow_error("Bitset size exceeds unsigned long long capacity");
        }
        return a[0] & ((1ull << numBits) - 1);
    }

    // 支持 to_ulong
    unsigned long to_ulong() const {
        if (numBits > sizeof(unsigned long) * CHAR_BIT) {
            throw overflow_error("Bitset size exceeds unsigned long capacity");
        }
        return static_cast<unsigned long>(a[0] & ((1ul << numBits) - 1));
    }

    // 支持 print(用于调试)
    void print() const {
        for (int i = 0; i < numBits; ++i) {
            cout << (*this)[i];
            if ((i + 1) % W == 0) cout << " ";
        }
        cout << endl;
    }

    class iterator {
    public:
        using iterator_category = bidirectional_iterator_tag;
        using difference_type = int;
        using value_type = int;
        using pointer = const int*;
        using reference = const int&;

    private:
        const Bitset* bitset;
        int index;

    public:
        iterator(const Bitset* bitset, int index) : bitset(bitset), index(index) {}

        value_type operator*() const { return index; }

        iterator& operator++() {
            index = bitset->nextLowestSetBit(index);
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        iterator& operator--() {
            if (index == -1) {
                index = bitset->highestSetBit();
            } else {
                index = bitset->nextHighestSetBit(index);
            }
            return *this;
        }

        iterator operator--(int) {
            iterator tmp = *this;
            --(*this);
            return tmp;
        }

        friend bool operator==(const iterator& a, const iterator& b) {
            return a.index == b.index;
        }

        friend bool operator!=(const iterator& a, const iterator& b) {
            return a.index != b.index;
        }
    };

    class reverse_iterator {
    public:
        using iterator_category = bidirectional_iterator_tag;
        using difference_type = int;
        using value_type = int;
        using pointer = const int*;
        using reference = const int&;

    private:
        const Bitset* bitset;
        int index;

    public:
        reverse_iterator(const Bitset* bitset, int index) : bitset(bitset), index(index) {}

        value_type operator*() const { return index; }

        reverse_iterator& operator++() {
            index = bitset->nextHighestSetBit(index);
            return *this;
        }

        reverse_iterator operator++(int) {
            reverse_iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        reverse_iterator& operator--() {
            if (index == -1) {
                index = bitset->lowestSetBit();
            } else {
                index = bitset->nextLowestSetBit(index);
            }
            return *this;
        }

        reverse_iterator operator--(int) {
            reverse_iterator tmp = *this;
            --(*this);
            return tmp;
        }

        friend bool operator==(const reverse_iterator& a, const reverse_iterator& b) {
            return a.index == b.index;
        }

        friend bool operator!=(const reverse_iterator& a, const reverse_iterator& b) {
            return a.index != b.index;
        }
    };

    iterator begin() const {
        int idx = lowestSetBit();
        return idx == -1 ? end() : iterator(this, idx);
    }

    iterator end() const {
        return iterator(this, numBits);
    }

    reverse_iterator rbegin() const {
        return reverse_iterator(this, highestSetBit());
    }

    reverse_iterator rend() const {
        return reverse_iterator(this, -1);
    }
};
const int N=5005,M=1000005;
int n,m;
int a[M],b[M];
int fa[N*4];
int siz[N*4];
int num[N*4][2];
int getf(int v)
{
    if(v==fa[v]) return v;
    else return fa[v]=getf(fa[v]);
}
void merge(int u,int v)
{
    int fu=getf(u),fv=getf(v);
    if(fu!=fv)
    {
        num[fu][0]+=num[fv][(fu>n*2)^(fv>n*2)];
        num[fu][1]+=num[fv][(fu>n*2)^(fv>n*2)^1];
        fa[fv]=fu;
    }
    return;
}
vector<pair<int,int>>G[N*2];
int col[N*2];
int cnt[2];
bitset<N>f[N*2];
int tot=0;
int rt[N*2],c[N*2][2];
vector<int>pos;
void dfs(int u,int color)
{
    pos.emplace_back(u);
    col[u]=color;
    cnt[color]++;
    for(auto [v,w]:G[u])
        if(col[v]==-1) dfs(v,color^w);
    return;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        cin>>a[i]>>b[i];
    for(int i=1;i<=n*4;i++)
        fa[i]=i,num[i][0]=1;
    vector<int>val;
    for(int i=1;i<=n*2;i++)
        val.emplace_back(1);
    int sum=0;
    for(int i=m;i>=1;i--)
    {
        int u=a[i],v=b[i];
        if(getf(u)==getf(v)||getf(u+n*2)==getf(v+n*2)) continue;
        if(getf(u)==getf(v+n*2)||getf(u+n*2)==getf(v)) continue;
        u=getf(u),v=getf(v);
        int w=1;
        cnt[0]=num[u][0],cnt[1]=num[u][1];
        if(u>n*2) w^=1,u-=n*2;
        int cu[2]={cnt[0],cnt[1]};
        if(cnt[0]>cnt[1]) swap(cnt[0],cnt[1]);
        sum-=cnt[0];
        val.erase(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]));
        cnt[0]=num[v][0],cnt[1]=num[v][1];
        if(v>n*2) w^=1,v-=n*2;
        int cv[2]={cnt[0],cnt[1]};
        if(cnt[0]>cnt[1]) swap(cnt[0],cnt[1]);
        sum-=cnt[0];
        val.erase(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]));
        cnt[0]=cu[0]+cv[w],cnt[1]=cu[1]+cv[w^1];
        if(cnt[0]>cnt[1]) swap(cnt[0],cnt[1]);
        sum+=cnt[0];
        val.insert(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]),cnt[1]-cnt[0]);
//             cerr<<"sum"<<sum<<'\n';
//             cerr<<"ins"<<cu[0]<<" "<<cv[1]<<"\n";
//             int tmp=0;
//             for(auto [c0,c1]:val)
//                 cerr<<"find"<<c0<<" "<<c1<<"\n",tmp+=c0;
//        assert(tmp==sum);
        if(sum>n)
        {
            val.erase(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]));
            sum-=cnt[0];
            cnt[0]=cu[0]+cv[w^1],cnt[1]=cu[1]+cv[w];
            if(cnt[0]>cnt[1]) swap(cnt[0],cnt[1]);
            val.insert(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]),cnt[1]-cnt[0]);
            sum+=cnt[0];
            if(w)
            {
                merge(u,v);
                merge(u+n*2,v+n*2);
            }
            else
            {
                merge(u,v+n*2);
                merge(u+n*2,v);
            }
            G[u].emplace_back(v,w^1);
            G[v].emplace_back(u,w^1);
            continue;
        }
        int ret=n-sum;
        Bitset f(N);
        f.set(0);
        for(auto c10:val)
        {
            f|=f<<c10;
            if(f[ret]) break;
        }
        if(!f[ret])
        {
            val.erase(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]));
            sum-=cnt[0];
            cnt[0]=cu[0]+cv[w^1],cnt[1]=cu[1]+cv[w];
            if(cnt[0]>cnt[1]) swap(cnt[0],cnt[1]);
            val.insert(lower_bound(val.begin(),val.end(),cnt[1]-cnt[0]),cnt[1]-cnt[0]);
            sum+=cnt[0];
            if(w)
            {
                merge(u,v);
                merge(u+n*2,v+n*2);
            }
            else
            {
                merge(u,v+n*2);
                merge(u+n*2,v);
            }
            G[u].emplace_back(v,w^1);
            G[v].emplace_back(u,w^1);
            continue;
        }
        G[u].emplace_back(v,w);
        G[v].emplace_back(u,w);
        if(w)
        {
            merge(u,v+n*2);
            merge(u+n*2,v);
        }
        else
        {
            merge(u,v);
            merge(u+n*2,v+n*2);
        }
//        cerr<<"Add"<<i<<"\n";
    }
    fill(col+1,col+n*2+1,-1);
    f[0][0]=1;
    tot=0;
    for(int u=1;u<=n*2;u++)
    {
        if(col[u]==-1)
        {
            cnt[0]=cnt[1]=0;
            dfs(u,0);
            rt[++tot]=u;
            c[tot][0]=cnt[0],c[tot][1]=cnt[1];
            f[tot]=(f[tot-1]<<cnt[0])|(f[tot-1]<<cnt[1]);
        }
    }
    assert(f[tot][n]);
    fill(col+1,col+n*2+1,-1);
    int ret=n;
    for(int i=tot;i>=1;i--)
    {
        int u=rt[i];
        if(ret>=c[i][0]&&f[i-1][ret-c[i][0]])
        {
            ret-=c[i][0];
            dfs(u,0);
        }
        else
        {
            ret-=c[i][1];
            dfs(u,1);
        }
    }
    for(int u=1;u<=n*2;u++)
        cout<<col[u];
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 9756kb

input:

2 4
1 3
2 4
1 4
1 2

output:

0101

result:

ok Output is valid. OK

Test #2:

score: 0
Accepted
time: 1ms
memory: 7668kb

input:

3 7
2 5
1 3
4 6
2 6
4 5
2 4
5 6

output:

001101

result:

ok Output is valid. OK

Test #3:

score: 0
Accepted
time: 1ms
memory: 5628kb

input:

1 0

output:

10

result:

ok Output is valid. OK

Test #4:

score: 0
Accepted
time: 1ms
memory: 7956kb

input:

1 1
1 2

output:

01

result:

ok Output is valid. OK

Test #5:

score: 0
Accepted
time: 1ms
memory: 7660kb

input:

2 3
2 4
3 4
1 2

output:

0110

result:

ok Output is valid. OK

Test #6:

score: 0
Accepted
time: 1ms
memory: 7600kb

input:

3 8
4 6
3 5
1 4
2 4
1 6
1 2
3 4
4 5

output:

010101

result:

ok Output is valid. OK

Test #7:

score: 0
Accepted
time: 1ms
memory: 7656kb

input:

4 9
4 7
3 8
1 5
2 7
2 8
6 8
7 8
1 4
1 6

output:

01010110

result:

ok Output is valid. OK

Test #8:

score: 0
Accepted
time: 1ms
memory: 9924kb

input:

5 16
3 6
9 10
2 7
1 10
1 5
2 10
3 5
5 6
3 4
2 5
4 5
3 8
4 7
6 8
1 6
7 10

output:

0010111010

result:

ok Output is valid. OK

Test #9:

score: 0
Accepted
time: 1ms
memory: 7700kb

input:

6 13
4 5
2 9
3 8
4 8
4 11
10 12
3 4
3 9
5 11
2 8
5 10
5 8
1 11

output:

110110001001

result:

ok Output is valid. OK

Test #10:

score: 0
Accepted
time: 1ms
memory: 7648kb

input:

12 153
1 24
16 18
7 14
1 16
20 21
9 14
21 22
4 5
17 24
4 12
5 17
13 24
14 15
12 23
12 16
8 11
14 24
9 16
2 5
6 19
11 17
4 22
4 7
6 16
7 20
8 15
5 24
2 10
10 21
21 24
1 12
11 19
18 21
18 24
12 17
13 22
7 9
13 23
4 9
11 13
15 21
5 7
2 4
15 16
17 19
11 16
11 20
7 8
4 15
13 14
6 18
2 19
9 13
23 24
4 21
...

output:

000011100110010001111110

result:

ok Output is valid. OK

Test #11:

score: -100
Runtime Error

input:

259 33757
472 500
65 336
138 469
307 442
427 458
43 239
17 508
460 466
108 393
79 92
250 483
44 277
17 132
35 57
155 499
184 474
246 272
274 418
457 458
338 372
196 514
31 208
117 187
90 229
153 284
189 355
16 337
146 456
269 271
279 412
305 336
303 441
399 472
85 286
91 97
157 437
137 379
71 360
27...

output:


result: