QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#667501 | #7686. The Phantom Menace | lamkappa | WA | 6ms | 19428kb | C++20 | 11.9kb | 2024-10-22 23:37:00 | 2024-10-22 23:37:02 |
Judging History
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
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, 1007};
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] = {1, 1};
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;
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] - 'a'));
}
}
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] - 'a'));
}
}
for(int offset=0; offset<m; 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;
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 == B2[h];
for(auto[h, x] : B2) fl &= x == B1[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++;
// auto cnt1 = cnt;
for(auto[h, _] : A2) mpA2[h] = cnt++;
auto cntAB = cnt;
for(auto[h, _] : B1) mpB1[h] = cnt++;
// auto cnt2 = cnt;
for(auto[h, _] : B2) mpB2[h] = cnt++;
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(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], mpB1[a]);
g.add_edge(mpB1[a], mpB2[b]);
// g.add_edge(mpB2[b], mpA1[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
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Wrong Answer
time: 6ms
memory: 19428kb
input:
2 3 3 abc ghi def bcd efg hia 1 3 abc def
output:
-1 -1
result:
wrong answer Jury has the answer but participant has not (test case 1)