这题 STL 解法不多说,外层一个 unordered_map
套内层 set
,按照同行、同列、同对角线(右上和右下)这样存储即可。
然后 AcWing 对 STL 极其不友好(本题 STL 套 STL 就更不友好了),开足所有优化还是比别的 OJ 要慢一些。不过 CSP 认证倒是自带 O2 优化,所以火车头加上就完事了。
但是 AcWing 上的第 11 组数据我硬卡了半天没卡过去,以下代码我重复提交了好几次,然后某一次评测机运气好跑得快就过了。只能说 AcWing 卡常一直是没法解决的问题,确实比较影响体验。下面这个代码重复多交几遍就是有概率能过。
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <stdio.h>
#include <assert.h>
#include <unordered_map>
#include <set>
#include <vector>
#include <algorithm>
#define getchar getchar_unlocked
#define putchar putchar_unlocked
typedef long long i64;
const int N = 100010, INF = 1145141919;
int n, m, p, q;
int u, v, t;
std::pair<int, int> a[N];
int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
std::pair<int, int> shift(const std::pair<int, int>& o, int dir, int d) { return std::make_pair(o.first + d * dx[dir], o.second + d * dy[dir]); }
namespace mp
{
int n, m; // x : [1, n] y : [1, m]
// row : same y col : same x diag_pos : same (x - y) diag_neg : same (x + y)
// first : x/y/x-y/x+y second.first : y/x second.second : id
std::unordered_map<int, std::set<std::pair<int, int>>> row, col, diag_pos, diag_neg;
inline void init(int _n, int _m) { n = _n, m = _m; }
inline void insert(int x, int y, int id)
{
row[y].insert(std::make_pair(x, id));
col[x].insert(std::make_pair(y, id));
diag_pos[x - y].insert(std::make_pair(x, id));
diag_neg[x + y].insert(std::make_pair(x, id));
}
inline void remove(int x, int y, int id) // assume exist
{
row[y].erase(std::make_pair(x, id));
col[x].erase(std::make_pair(y, id));
diag_pos[x - y].erase(std::make_pair(x, id));
diag_neg[x + y].erase(std::make_pair(x, id));
}
// <dis, pt_id> pt_id = INF : no neighbor
inline std::pair<int, int> find_neighbor(int x, int y, int dir)
{
std::set<std::pair<int, int>>::iterator it;
std::pair<int, int> ret = std::make_pair(0, 0);
switch (dir)
{
case 0:
if (!row.count(y)) return std::make_pair(n - x, INF);
it = row[y].lower_bound(std::make_pair(x + 1, 0));
ret = (it == row[y].end()) ? std::make_pair(n - x, INF) : std::make_pair(it->first - x, it->second);
break;
case 1:
if (!diag_pos.count(x - y)) return std::make_pair(std::min(n - x, m - y), INF);
it = diag_pos[x - y].lower_bound(std::make_pair(x + 1, 0));
ret = (it == diag_pos[x - y].end()) ? std::make_pair(std::min(n - x, m - y), INF) : std::make_pair(it->first - x, it->second);
break;
case 2:
if (!col.count(x)) return std::make_pair(m - y, INF);
it = col[x].lower_bound(std::make_pair(y + 1, 0));
ret = (it == col[x].end()) ? std::make_pair(m - y, INF) : std::make_pair(it->first - y, it->second);
break;
case 3:
if (!diag_neg.count(x + y)) return std::make_pair(std::min(x - 1, m - y), INF);
it = diag_neg[x + y].lower_bound(std::make_pair(x, 0));
ret = (it == diag_neg[x + y].begin()) ? std::make_pair(std::min(x - 1, m - y), INF) : (--it, std::make_pair(x - it->first, it->second));
break;
case 4:
if (!row.count(y)) return std::make_pair(x - 1, INF);
it = row[y].lower_bound(std::make_pair(x, 0));
ret = (it == row[y].begin()) ? std::make_pair(x - 1, INF) : (--it, std::make_pair(x - it->first, it->second));
break;
case 5:
if (!diag_pos.count(x - y)) return std::make_pair(std::min(x - 1, y - 1), INF);
it = diag_pos[x - y].lower_bound(std::make_pair(x, 0));
ret = (it == diag_pos[x - y].begin()) ? std::make_pair(std::min(x - 1, y - 1), INF) : (--it, std::make_pair(x - it->first, it->second));
break;
case 6:
if (!col.count(x)) return std::make_pair(y - 1, INF);
it = col[x].lower_bound(std::make_pair(y, 0));
ret = (it == col[x].begin()) ? std::make_pair(y - 1, INF) : (--it, std::make_pair(y - it->first, it->second));
break;
case 7:
if (!diag_neg.count(x + y)) return std::make_pair(std::min(n - x, y - 1), INF);
it = diag_neg[x + y].lower_bound(std::make_pair(x + 1, 0));
ret = (it == diag_neg[x + y].end()) ? std::make_pair(std::min(n - x, y - 1), INF) : std::make_pair(it->first - x, it->second);
break;
default:
break;
}
return ret;
}
}
std::set<std::pair<int, int>> vis;
std::pair<int, int> dir_res[10];
int main()
{
scanf("%d%d%d%d", &n, &m, &p, &q);
mp::init(n, m);
for (int i = 1; i <= p; ++i)
{
scanf("%d%d", &a[i].first, &a[i].second), mp::insert(a[i].first, a[i].second, i);
assert(!vis.count(a[i])), vis.insert(a[i]);
assert(1 <= a[i].first && a[i].first <= n), assert(1 <= a[i].second && a[i].second <= m);
}
while (q--)
{
scanf("%d%d%d", &u, &v, &t);
assert(1 <= u && u <= n), assert(1 <= v && v <= m), assert(1 <= t && t <= 7);
// calculate min_dis
std::pair<int, int> ret = std::make_pair(INF, INF);
for (int dir = 0; dir < 8; ++dir) dir_res[dir] = mp::find_neighbor(u, v, dir), ret = std::min(ret, dir_res[dir]);
int k = (ret.second == INF) ? 0 : ret.first;
if (!k) continue;
std::vector<std::pair<int, std::pair<int, int>>> change;
for (int dir = 0; dir < 8; ++dir)
{
if (dir_res[dir].first == k && dir_res[dir].second < INF)
{
std::pair<int, int> nxt = shift(std::make_pair(u, v), (dir + t) & 7, k);
change.push_back(std::make_pair(dir_res[dir].second, nxt));
}
}
for (auto& x : change)
{
mp::remove(a[x.first].first, a[x.first].second, x.first);
mp::insert(x.second.first, x.second.second, x.first);
a[x.first] = x.second;
}
}
// putchar('\n');
// for (int i = 1; i <= p; ++i) wr(a[i].first), putchar(' '), wr(a[i].second), putchar('\n');
i64 res = 0;
for (int i = 1; i <= p; ++i) res ^= (1ll * i * a[i].first) + a[i].second;
wr(res);
}