QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#667594#7686. The Phantom MenacelamkappaCompile Error//C++2019.3kb2024-10-23 00:26:512024-10-23 00:26:54

Judging History

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

  • [2024-10-23 00:26:54]
  • 评测
  • [2024-10-23 00:26:51]
  • 提交

answer

#include<bits/stdc++.h>
using namespace std;

#ifndef STL_PBDS
#define STL_PBDS

#define _EXT_CODECVT_SPECIALIZATIONS_H 1
#define _EXT_ENC_FILEBUF_H 1
#include <bits/extc++.h>
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;

// 平衡树
template<typename K_T,
    typename Cmp = std::less<K_T>,
    typename V_T = __gnu_pbds::null_type
>
using order_set = __gnu_pbds::tree<
    K_T,                                                // key_type
    V_T,                                                // value_type
    Cmp,                                                // comparator
    __gnu_pbds::rb_tree_tag,                            // tag
    __gnu_pbds::tree_order_statistics_node_update       // policy
>;
template<typename K_T,
    typename V_T = __gnu_pbds::null_type,
    typename Cmp = std::less<K_T>
>
using order_map = order_set<K_T, Cmp, V_T>;
template<typename K_T, typename V_T, typename Cmp>
V_T& operator%(order_map<K_T,V_T,Cmp>&mp, const K_T&x){
    return mp.lower_bound(x)->second;
}
/*
tag:
rb_tree_tag                                 红黑树
splay_tree_tag                              Slpay
ov_tree_tag                                 向量树

Itr ::point_iterator

std::pair<point_iterator, bool> insert(T)   插入
bool erase(T/Itr)                           删除元素/迭代器
int order_of_key(T)                         返回排名
Itr find_by_order(T)                        排名对应元素
Itr lower_bound(T)/upper_bound(T)           二分查找
void join(order_set)                        合并
void split(T,order_set)                     保留<=,其余分离覆盖到order_set中
bool empty()                                判空
size_t size()                               大小
Itr begin()/end()                           首尾迭代器
*/

/***************/

// 堆
template<typename T,
    typename Cmp = std::greater<T>
>
using heap = __gnu_pbds::priority_queue<
    T,                                                  // type
    Cmp,                                                // comparator
    __gnu_pbds::pairing_heap_tag                        // tag
>;
/*
tag:
pairing_heap_tag        配对堆
thin_heap_tag           斐波那契堆
binomial_heap_tag       二项堆
binary_heap_tag         二叉堆

Itr ::point_iterator    可以指定为nullptr

usage:
Itr push(T)             入堆
void pop()              出堆
T top()                 堆顶
void modify(Itr, T)     修改
void join(heap)         合并,清空heap
bool empty()            判空
size_t size()           大小
void clear()            清空
*/

/***************/

// 哈希表
const int RANDOM = std::chrono::high_resolution_clock::now().time_since_epoch().count();
template<typename K_T>
struct Chash{
    int operator()(K_T x)const{return std::hash<K_T>{}(x)^RANDOM;}
};
template<typename K_T, typename V_T, typename Hash = Chash<K_T>>
using hash_table = __gnu_pbds::gp_hash_table<K_T, V_T, Hash>;

/*
tag:
cc_hash_table           拉链法
gp_hash_table           二次探测法

V_T& operaotr[](K_T)    映射
*/


// 字典树
using trie = __gnu_pbds::trie<
    std::string,                                    //
    __gnu_pbds::null_type,                          //
    __gnu_pbds::trie_string_access_traits<>,        //
    __gnu_pbds::pat_trie_tag,                       // tag
    __gnu_pbds::trie_prefix_search_node_update      // policy
>;
/*
Itr insert(string)                          插入
void erase(string)                          删除
void join(trie)                             合并trie
std::pair<Itr, Itr> prefix_range(string)    前缀遍历[beign,end)
*/

#endif

#ifndef DISJOINT_SET_UNION
#define DISJOINT_SET_UNION
// 并查集

struct DSU {
    std::vector<int> fa, sz, st;
    DSU() {}
    DSU(int n) {init(n);}
    void init(int n) {
        fa.resize(n);
        std::iota(fa.begin(), fa.end(), 0);
        sz.assign(n, 1);
        st.clear();
    }
    int find(int x) {
        while(x!=fa[x]) {
            x = fa[x] = fa[fa[x]];
        }
        return x;
    }
    bool same(int x, int y) {
        return find(x) == find(y);
    }
    bool merge(int x, int y) {
        x = find(x); y = find(y);
        if(x==y) { return false; }
        if(sz[x]<sz[y]) { std::swap(x,y); }
        sz[x] += sz[y];
        st.push_back(y);
        fa[y] = x;
        return true;
    }
    int get_size(int x) {
        return sz[find(x)];
    }
    void clear() {
        while(!st.empty()) {
            int x = st.back(), p = find(x);
            fa[p] = p; sz[p] = 1;
            fa[x] = x; sz[x] = 1;
            st.pop_back();
        }
    }
};

#endif

#ifndef EULER_LOOP
#define EULER_LOOP

struct EulerLoop{
    DSU dsu;
    std::vector<hash_table<int, int>> adj;

    EulerLoop(int n) : dsu(n){
        adj.assign(n, {});
    }

    void add_edge(int u, int v){
        adj[u][v]++;
        dsu.merge(u, v);
    }

    std::vector<int> find(int rt){
        std::vector<int> ans;
        // auto adj = this->adj;
        auto dfs = [&](auto&&dfs, int u)->void{
            while(!adj[u].empty()){
                auto v = adj[u].begin()->first;
                if(0 == --adj[u][v]){
                    adj[u].erase(v);
                }
                dfs(dfs, v);
            }
            ans.push_back(u);
        };
        dfs(dfs, rt);
        reverse(ans.begin(), ans.end());
        return ans;
    }

    bool connected(){
        return dsu.get_size(0) == adj.size();
    }

    bool empty()const{
        bool fl = true;
        for(const auto&x : adj){
            fl &= x.empty();
        }
        return fl;
    }
};

#endif

#ifndef MODINT_CPP
#define MODINT_CPP
// 模数循环群

using i64 = long long;
 
template<class T>
constexpr T qpow(T a,i64 b){
    if(0==a)return a;
    T res = 1;
    while(b){
        if(b&1) res *= a;
        a *= a;
        b >>= 1;
    }
    return res;
}
constexpr i64 mul(i64 a,i64 b,i64 p){
    i64 res = a*b - p*i64(1.L*a*b/p);
    res %= p;
    if(res<0) res += p;
    return res;
}
template<i64 P=0LL>
struct MLong{
    i64 x;
    constexpr MLong():x(0){}
    constexpr MLong(i64 x):x(norm(x%getMod())){}
    
    static i64 Mod;
    constexpr static i64 getMod(){
        return P>0?P:Mod;
    }
    constexpr static void setMod(i64 Mod_){
        Mod = Mod_;
    }
    constexpr i64 norm(i64 x)const{
        if(x<0){
            x += getMod();
        }
        if(x>=getMod()){
            x -= getMod();
        }
        return x;
    }
    constexpr i64 val()const{
        return x;
    }
    explicit constexpr operator i64()const{
        return x;
    }
    constexpr MLong operator-()const{
        MLong res;
        res.x = norm(getMod() - x);
        return res;
    }
    constexpr MLong inv()const{
        assert(x != 0);
        return qpow(*this,getMod() - 2);
    }
    constexpr MLong &operator*=(MLong rhs)&{
        x = mul(x,rhs.x,getMod());
        return *this;
    }
    constexpr MLong &operator+=(MLong rhs)&{
        x = norm(x + rhs.x);
        return *this;
    }
    constexpr MLong &operator-=(MLong rhs)&{
        x = norm(x - rhs.x);
        return *this;
    }
    constexpr MLong &operator/=(MLong rhs)&{
        return *this *= rhs.inv();
    }
    friend constexpr MLong operator*(MLong lhs,MLong rhs){
        MLong res = lhs;
        res *= rhs;
        return res;
    }
    friend constexpr MLong operator+(MLong lhs,MLong rhs){
        MLong res = lhs;
        res += rhs;
        return res;
    }
    friend constexpr MLong operator-(MLong lhs,MLong rhs){
        MLong res = lhs;
        res -= rhs;
        return res;
    }
    friend constexpr MLong operator/(MLong lhs,MLong rhs){
        MLong res = lhs;
        res /= rhs;
        return res;
    }
    friend constexpr istream &operator>>(istream &is,MLong &a){
        i64 v;
        is >> v;
        a = MLong(v);
        return is;
    }
    friend constexpr ostream &operator<<(ostream &os,const MLong &a){
        return os << a.val();
    }
    friend constexpr bool operator==(MLong lhs,MLong rhs){
        return lhs.val() == rhs.val();
    }
    friend constexpr bool operator!=(MLong lhs,MLong rhs){
        return !(lhs == rhs);
    }
    friend constexpr bool operator<(MLong lhs,MLong rhs){
        return lhs.val() < rhs.val();
    }
    friend constexpr bool operator<=(MLong lhs,MLong rhs){
        return lhs < rhs || lhs == rhs;
    }
    friend constexpr bool operator>(MLong lhs,MLong rhs){
        return !(lhs <= rhs);
    }
    friend constexpr bool operator>=(MLong lhs,MLong rhs){
        return !(lhs < rhs);
    }
};
 
template<>
i64 MLong<0LL>::Mod = 1;
 
template<int P=0>
struct MInt{
    int x;
    constexpr MInt():x(0){}
    constexpr MInt(i64 x):x(norm(x%getMod())){}
    
    static int Mod;
    constexpr static int getMod(){
        return P>0?P:Mod;
    }
    constexpr static void setMod(int Mod_){
        Mod = Mod_;
    }
    constexpr int norm(int x)const{
        if(x<0){
            x += getMod();
        }
        if(x>=getMod()){
            x -= getMod();
        }
        return x;
    }
    constexpr int val()const{
        return x;
    }
    explicit constexpr operator int()const{
        return x;
    }
    constexpr MInt operator-()const{
        MInt res;
        res.x = norm(getMod() - x);
        return res;
    }
    constexpr MInt inv()const{
        assert(x != 0);
        return qpow(*this,getMod() - 2);
    }
    constexpr MInt &operator*=(MInt rhs)&{
        x = 1LL * x * rhs.x % getMod();
        return *this;
    }
    constexpr MInt &operator+=(MInt rhs)&{
        x = norm(x + rhs.x);
        return *this;
    }
    constexpr MInt &operator-=(MInt rhs)&{
        x = norm(x - rhs.x);
        return *this;
    }
    constexpr MInt &operator/=(MInt rhs)&{
        return *this *= rhs.inv();
    }
    friend constexpr MInt operator*(MInt lhs,MInt rhs){
        MInt res = lhs;
        res *= rhs;
        return res;
    }
    friend constexpr MInt operator+(MInt lhs,MInt rhs){
        MInt res = lhs;
        res += rhs;
        return res;
    }
    friend constexpr MInt operator-(MInt lhs,MInt rhs){
        MInt res = lhs;
        res -= rhs;
        return res;
    }
    friend constexpr MInt operator/(MInt lhs,MInt rhs){
        MInt res = lhs;
        res /= rhs;
        return res;
    }
    friend constexpr istream &operator>>(istream &is,MInt &a){
        i64 v;
        is >> v;
        a = MInt(v);
        return is;
    }
    friend constexpr ostream &operator<<(ostream &os,const MInt &a){
        return os << a.val();
    }
    friend constexpr bool operator==(MInt lhs,MInt rhs){
        return lhs.val() == rhs.val();
    }
    friend constexpr bool operator!=(MInt lhs,MInt rhs){
        return lhs.val() != rhs.val();
    }
    friend constexpr bool operator<(MInt lhs,MInt rhs){
        return lhs.val() < rhs.val();
    }
    friend constexpr bool operator<=(MInt lhs,MInt rhs){
        return lhs < rhs || lhs == rhs;
    }
    friend constexpr bool operator>(MInt lhs,MInt rhs){
        return !(lhs <= rhs);
    }
    friend constexpr bool operator>=(MInt lhs,MInt rhs){
        return !(lhs < rhs);
    }
};
 
template<>
int MInt<0>::Mod = 1;
 
template<int V,int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();
 
constexpr int P = 1000000007;
using Z = MInt<P>;

#endif

struct Hash{
    static constexpr std::size_t C = 1;
    using u64 = Z;
    using hash = std::array<u64, C>;

    hash val;

    Hash() { val.fill(0ull); }

    Hash(const std::initializer_list<u64>&list) {
        std::copy(list.begin(), list.end(), val.begin());
    }

    bool operator==(const Hash&o)const{
        return val == o.val;
    }
    Hash operator*(const Hash&o)const{
        Hash res;
        std::transform(val.begin(), val.end(), o.val.begin(), res.val.begin(), std::multiplies());
        return res;
    }
    Hash operator+(u64 y)const{
        Hash res = *this;
        for(auto&x : res.val) x += y;
        return res;
    }
    Hash operator+(const Hash&o)const{
        Hash res;
        std::transform(val.begin(), val.end(), o.val.begin(), res.val.begin(), std::plus());
        return res;
    }
    Hash operator-(u64 y)const{
        Hash res = *this;
        for(auto&x : res.val) x -= y;
        return res;
    }
    Hash operator-(const Hash&o)const{
        Hash res;
        std::transform(val.begin(), val.end(), o.val.begin(), res.val.begin(), std::minus());
        return res;
    }

};


// struct Hash{
//     static constexpr std::size_t C = 2;
//     using u64 = unsigned long long;
//     using hash = std::array<u64, C>;

//     hash val;

//     Hash() { val.fill(0ull); }

//     Hash(const std::initializer_list<u64>&list) {
//         std::copy(list.begin(), list.end(), val.begin());
//     }

//     bool operator==(const Hash&o)const{
//         return val == o.val;
//     }
//     Hash operator*(const Hash&o)const{
//         return {val[0] * o.val[0], val[1] * o.val[1]};
//     }
//     Hash operator+(u64 x)const{
//         return {val[0] + x, val[1] + x};
//     }
//     Hash operator+(const Hash&o)const{
//         return {val[0] + o.val[0], val[1] + o.val[1]};
//     }
//     Hash operator-(u64 x)const{
//         return {val[0] - x, val[1] - x};
//     }
//     Hash operator-(const Hash&o)const{
//         return {val[0] - o.val[0], val[1] - o.val[1]};
//     }

// };
// const int RANDOM = std::chrono::high_resolution_clock::now().time_since_epoch().count();
namespace std {
    template <>
    struct hash<Hash> {
        std::size_t operator()(Hash x)const{
            return std::accumulate(x.val.begin(), x.val.end(), 0, std::bit_xor());
        }
    };
}
const Hash M = Hash{51, 91};
constexpr int MAXM = 1e6+5;
Hash Mpow[MAXM];

hash_table<Hash, int> A1, A2, B1, B2;
hash_table<Hash, int> mpA1, mpA2;//, mpB1, mpB2;
signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    Mpow[0].val.fill(1ull);
    for(int i=1; i<MAXM; i++){
        Mpow[i] = Mpow[i-1] * M;
    }

    int T; cin >> T;
    while(T--){
        int n, m; cin >> n >> m;
        // if(n == 1 && m == 2112 && T == 0){
        //     cout << "-1\n"; continue;
        // }
        vector hA(n, vector<Hash>(m+1));
        auto hB = hA;
        for(int i=0; i<n; i++){
            string s; cin >> s;
            for(int j=1; j<=m; j++){
                hA[i][j] = (hA[i][j-1]*M + (s[j-1])*2);
            }
        }
        for(int i=0; i<n; i++){
            string s; cin >> s;
            for(int j=1; j<=m; j++){
                hB[i][j] = (hB[i][j-1]*M + (s[j-1])*2);
            }
        }

        for(int offset=m-1; offset>=0; offset--){
            A1.clear(); A2.clear(); B1.clear(); B2.clear();
            // hash_table<Hash, int> A1, A2, B1, B2;
            for(int i=0; i<n; i++){
                Hash a = hA[i][offset];
                Hash b = hA[i][m] - hA[i][offset] * Mpow[m-offset];
                A1[a]++; A2[b]++;
                // B1[b]++; B2[a]++;
            }
            for(int i=0; i<n; i++){
                Hash a = hB[i][m-offset];
                Hash b = hB[i][m] - hB[i][m-offset] * Mpow[offset];
                // A1[b]++; A2[a]++;
                B1[a]++; B2[b]++;
            }
            bool fl = true;
            if(A1.size() != B2.size() || A2.size() != B1.size()) continue;
            for(auto[h, x] : A1) fl &= x == B2[h];
            for(auto[h, x] : A2) fl &= x == B1[h];
            // for(auto[h, x] : B1) fl &= x == A2[h];
            // for(auto[h, x] : B2) fl &= x == A1[h];
            // for(auto[h, x] : A1) fl &= (x % 2 == 0) && x == B2[h];
            // for(auto[h, x] : A2) fl &= (x % 2 == 0) && x == B1[h];
            // for(auto[h, x] : B1) fl &= (x % 2 == 0);
            // for(auto[h, x] : B2) fl &= (x % 2 == 0);
            if(fl){
                mpA1.clear(), mpA2.clear();//, mpB1.clear(), mpB2.clear();
                // hash_table<Hash, int> mpA1, mpA2, mpB1, mpB2;
                int cnt = 0;
                for(auto[h, _] : A1) mpA1[h] = cnt++;
                for(auto[h, _] : A2) mpA2[h] = cnt++;
                auto cntAB = cnt;
                // for(auto[h, _] : B2) mpB2[h] = cnt++;
                // for(auto[h, _] : B1) mpB1[h] = cnt++;
                cnt *= 2;
                EulerLoop g(cnt);
                hash_table<int, Hash> pos;
                hash_table<Hash, vector<int>> segA, segB;
                for(int i=0; i<n; i++){
                    Hash a = hA[i][offset];
                    Hash b = hA[i][m] - hA[i][offset] * Mpow[m-offset];
                    g.add_edge(mpA1[a]+cntAB, mpA1[a]);
                    // g.add_edge(mpB2[a], mpA1[a]);
                    g.add_edge(mpA1[a], mpA2[b]);
                    // g.add_edge(mpA2[b], mpB1[b]);
                    pos[mpA1[a]] = a;
                    pos[mpA2[b]] = b;
                    Hash ab = b + a * Mpow[m-offset];
                    segA[ab].push_back(i);
                }
                for(int i=0; i<n; i++){
                    Hash a = hB[i][m-offset];
                    Hash b = hB[i][m] - hB[i][m-offset] * Mpow[offset];
                    g.add_edge(mpA2[a], mpA2[a]+cntAB);
                    g.add_edge(mpA2[a]+cntAB, mpA1[b]+cntAB);
                    // g.add_edge(mpA2[a], mpB1[a]);
                    // g.add_edge(mpB1[a], mpB2[b]);
                    // g.add_edge(mpB2[b], mpA1[b]);
                    pos[mpA2[a]+cntAB] = a;
                    pos[mpA1[b]+cntAB] = b;
                    // pos[mpB1[a]] = a;
                    // pos[mpB2[b]] = b;
                    Hash ab = b + a * Mpow[m-offset];
                    segB[ab].push_back(i);
                }
                if(!g.connected()) continue;
                auto ans = g.find(0);
                if(!g.empty()) continue;
                vector<int> ans_A, ans_B;
                for(int i=0; i<ans.size(); i++){
                    auto x = ans[i];
                    auto y = ans[(i+1)%ans.size()];
                    if(x < cntAB && y < cntAB){
                        // if(x > y) swap(x, y);
                        Hash a = pos[x], b = pos[y];
                        Hash ab = b + a * Mpow[m-offset];
                        if(segA[ab].empty()) continue;
                        ans_A.push_back(segA[ab].back());
                        segA[ab].pop_back();
                    }else if(x >= cntAB && y >=cntAB){
                        // if(x < y) swap(x, y);
                        Hash a = pos[x], b = pos[y];
                        Hash ab = b + a * Mpow[m-offset];
                        if(segB[ab].empty()) continue;
                        ans_B.push_back(segB[ab].back());
                        segB[ab].pop_back();
                    }
                }
                if(ans_A.size() != n || ans_B.size() != n) continue;
                for(auto x : ans_A) cout << x+1 << ' '; cout << '\n';
                for(auto x : ans_B) cout << x+1 << ' '; cout << '\n';


                goto NEXT_CASE;
            }
        }
        cout << "-1\n";

        NEXT_CASE:;
    }

    
    return 0;
}

Details

In file included from /usr/include/c++/13/numeric:62,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:58,
                 from answer.code:1:
/usr/include/c++/13/bits/stl_numeric.h: In instantiation of ‘constexpr _Tp std::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation) [with _InputIterator = MInt<1000000007>*; _Tp = int; _BinaryOperation = bit_xor<void>]’:
answer.code:540:35:   required from here
/usr/include/c++/13/bits/stl_numeric.h:169:29: error: no match for call to ‘(std::bit_xor<void>) (std::remove_reference<int&>::type, MInt<1000000007>&)’
  169 |         __init = __binary_op(_GLIBCXX_MOVE_IF_20(__init), *__first);
      |                  ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/13/string:49,
                 from /usr/include/c++/13/bitset:52,
                 from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:52:
/usr/include/c++/13/bits/stl_function.h:964:9: note: candidate: ‘template<class _Tp, class _Up> constexpr decltype ((forward<_Tp>(__t) ^ forward<_Up>(__u))) std::bit_xor<void>::operator()(_Tp&&, _Up&&) const’
  964 |         operator()(_Tp&& __t, _Up&& __u) const
      |         ^~~~~~~~
/usr/include/c++/13/bits/stl_function.h:964:9: note:   template argument deduction/substitution failed:
/usr/include/c++/13/bits/stl_function.h: In substitution of ‘template<class _Tp, class _Up> constexpr decltype ((forward<_Tp>(__t) ^ forward<_Up>(__u))) std::bit_xor<void>::operator()(_Tp&&, _Up&&) const [with _Tp = int; _Up = MInt<1000000007>&]’:
/usr/include/c++/13/bits/stl_numeric.h:169:22:   required from ‘constexpr _Tp std::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation) [with _InputIterator = MInt<1000000007>*; _Tp = int; _BinaryOperation = bit_xor<void>]’
answer.code:540:35:   required from here
/usr/include/c++/13/bits/stl_function.h:966:44: error: no match for ‘operator^’ (operand types are ‘int’ and ‘MInt<1000000007>’)
  966 |         -> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))
      |                     ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/13/bits/stl_function.h:966:44: note: candidate: ‘operator^(int, int)’ (built-in)
/usr/include/c++/13/bits/stl_function.h:966:44: note:   no known conversion for argument 2 from ‘MInt<1000000007>’ to ‘int’
In file included from /usr/include/x86_64-linux-gnu/c++/13/bits/stdc++.h:41:
/usr/include/c++/13/cstddef:145:3: note: candidate: ‘constexpr std::byte std::operator^(byte, byte)’
  145 |   operator^(byte __l, byte __r) noexcept
      |   ^~~~~~~~
/usr/include/c++/13/cstddef:145:18: note:   no known conversion for argument 1 from ‘int’ to ‘std::byte’
  145 |   operator^(byte __l, byte __r) noexcept
      |             ~~~~~^~~