QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#91831 | #5504. Flower Garden | Denisov | TL | 0ms | 0kb | C++20 | 10.0kb | 2023-03-29 17:44:13 | 2023-03-29 17:44:17 |
Judging History
answer
//#pragma GCC optimize("Ofast", "unroll-loops")
//#pragma GCC target("sse", "sse2", "sse3", "ssse3", "sse4")
#include <bits/stdc++.h>
#define all(a) a.begin(),a.end()
#define len(a) (int)(a.size())
#define mp make_pair
#define pb push_back
#define fir first
#define sec second
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
template<typename T>
inline bool umin(T &a, T b) {
if (b < a) {
a = b;
return true;
}
return false;
}
template<typename T>
inline bool umax(T &a, T b) {
if (a < b) {
a = b;
return true;
}
return false;
}
#ifdef LOCAL
#define D for (bool _FLAG = true; _FLAG; _FLAG = false)
#define LOG(...) print(#__VA_ARGS__" ::", __VA_ARGS__) << endl
template <class ...Ts> auto &print(Ts ...ts) { return ((cerr << ts << " "), ...); }
#else
#define D while (false)
#define LOG(...)
#endif // LOCAL
const int max_n = 5e5 + 18 * 1e5 * 4, inf = 1000111222;
template<typename Edge>
class GraphIterator {
public:
class OutgoingEdges {
public:
OutgoingEdges(const GraphIterator *g, int l, int r): g(g), l(l), r(r) {
}
const pair<int, Edge>* begin() const {
if (l == r) {
return 0;
}
return &g->edges[l];
}
const pair<int, Edge>* end() const {
if (l == r) {
return 0;
}
return &g->edges[r];
}
int l, r;
const GraphIterator *g;
};
void clear() {
edges.clear();
start.clear();
prepared = false;
}
void add_edge(int from, const Edge &e) {
assert(!prepared && from >= 0);
edges.push_back({from, e});
}
void prepare() {
assert(!prepared);
int n = 0;
for (const auto &e : edges) {
n = max(n, e.first);
}
n += 2;
start.resize(n);
for (const auto &e : edges) {
++start[e.first + 1];
}
for (int i = 1; i < n; ++i) {
start[i] += start[i - 1];
}
auto counter = start;
for (int i = 0; i < (int)edges.size(); ) {
if (start[edges[i].first] <= i && i < counter[edges[i].first]) {
i = counter[edges[i].first];
continue;
}
swap(edges[i], edges[counter[edges[i].first]]);
}
prepared = true;
}
OutgoingEdges operator [] (int from) const {
assert(prepared);
if (from < 0 || from + 1 >= start.size()) {
return {this, 0, 0};
}
return {this, start[from], start[from + 1]};
}
vector<pair<int, Edge>> edges;
vector<int> start;
bool prepared = false;
};
GraphIterator<int> g, gr;
pii e[max_n];
pii e1[max_n];
int n, num = 0;
vector <int> t, t1;
inline void upd (int v, int tl, int tr, int l, int r, int id, bool from) {
if (l > r) return;
if (tl == l && tr == r) {
if (from) {
g.add_edge(id, t1[v]);
//e[num++] = {id, t1[v]};
}
else {
g.add_edge(t[v], id);
//e[num++] = {t[v], id};
}
return;
}
int tm = (tl + tr) >> 1;
upd(v << 1, tl, tm, l, min(r, tm), id, from);
upd(v << 1 | 1, tm + 1, tr, max(tm + 1, l), r, id, from);
}
int mx;
inline int build (int v, int tl, int tr) {
umax(mx, 3 * n + v + 1);
t[v] = 3 * n + v;
if (tl == tr) {
g.add_edge(tr, 3 * n + v);
//e[num++] = {tr, 3 * n + v};
return 3 * n + v;
}
int tm = (tl + tr) >> 1;
int L = build(v << 1, tl, tm);
int R = build(v << 1 | 1, tm + 1, tr);
g.add_edge(L, 3 * n + v);
g.add_edge(R, 3 * n + v);
//e[num++] = {L, 3 * n + v};
//e[num++] = {R, 3 * n + v};
return 3 * n + v;
}
inline int build1 (int v, int tl, int tr) {
t1[v] = mx++;
if (tl == tr) {
g.add_edge(t1[v], tr);
//e[num++] = {t1[v], tr};
return t1[v];
}
int tm = (tl + tr) >> 1;
int L = build1(v << 1, tl, tm);
int R = build1(v << 1 | 1, tm + 1, tr);
g.add_edge(t1[v], L);
g.add_edge(t1[v], R);
//e[num++] = {t1[v],L};
//e[num++] = {t1[v],R};
return t1[v];
}
vector <int> used, order, cl, w, p, p1;
inline void dfs (int v) {
used[v] = 1;
auto cur = g[v];
for (int i = cur.l; i < cur.r; i++) {
int to = cur.g->edges[i].second;
//if (e[i].first != v) break;
//int to = e[i].second;
if (!used[to]) {
dfs(to);
}
}
order.pb(v);
}
inline void dfs1 (int v, int c) {
used[v] = 2;
cl[v] = c;
w[c] += v < 3 * n;
auto cur = gr[v];
for (int i = cur.l; i < cur.r; i++) {
int to = cur.g->edges[i].second;
//if (e1[i].first != v) break;
//int to = e1[i].second;
if (used[to] == 1) {
dfs1(to, c);
}
}
}
vector <int> ans;
inline void color (int v) {
ans[v] = 1;
auto cur = g[v];
for (int i = cur.l; i < cur.r; i++) {
int to = cur.g->edges[i].second;
//if (e[i].first != v) break;
//int to = e[i].second;
if (!ans[to]) {
color(to);
}
}
}
inline void color1 (int v) {
ans[v] = 0;
auto cur = gr[v];
for (int i = cur.l; i < cur.r; i++) {
int to = cur.g->edges[i].second;
//if (e[i].first != v) break;
//int to = e[i].second;
if (ans[to]) {
color1(to);
}
}
}
inline void test_case () {
ans.clear();
p.clear();
p1.clear();
t.clear();
t1.clear();
cl.clear();
w.clear();
used.clear();
g.clear();
gr.clear();
order.clear();
num = 0;
mx = 0;
int q;
cin >> n >> q;
t.resize(3 * 4 * n);
t1.resize(3 * 4 * n);
build(1, 0, 3 * n - 1);
build1(1, 0, 3 * n - 1);
for (int i = 0, a, b, c, d; i < q; i++) {
cin >> a >> b >> c >> d;
--a, --b, --c, --d;
int cur = mx;
upd(1, 0, 3 * n - 1, c, d, cur, false);
upd(1, 0, 3 * n - 1, a, b, cur, true);
++mx;
}
//LOG("here");
int N = mx;
for (auto &i : g.edges) {
gr.add_edge(i.second, i.first);
}
g.prepare();
gr.prepare();
/*for (int i = 0; i < num; i++) {
e1[i] = {e[i].second, e[i].first};
}
sort(e, e + num);
sort(e1, e1 + num);
p.resize(N);
p1.resize(N);
for (int i = 0, j = 0; i < N; i++) {
while (j < num && e[j].first < i) {
++j;
}
p[i] = j;
}
for (int i = 0, j = 0; i < N; i++) {
while (j < num && e1[j].first < i) {
++j;
}
p1[i] = j;
}*/
used.resize(N);
for (int i = 0; i < N; i++) {
if (!used[i]) {
dfs(i);
}
}
reverse(all(order));
w.resize(N);
cl.resize(N);
int cmp = 0;
for (int i : order) {
if (used[i] == 1) {
dfs1(i, cmp);
++cmp;
}
}
for (int i = 0; i < cmp; i++) {
if (w[i] > 2 * n) {
cout << "NIE\n";
return;
}
}
/*for (int it = 0; it < num; it++) {
pii i = e[it];
e[it] = {cl[i.first], cl[i.second]};
i = e1[it];
e1[it] = {cl[i.first], cl[i.second]};
}
sort(e, e + num);
sort(e1, e1 + num);
for (int i = 0, j = 0; i < cmp; i++) {
while (j < num && e[j].first < i) {
++j;
}
p[i] = j;
}
for (int i = 0, j = 0; i < cmp; i++) {
while (j < num && e1[j].first < i) {
++j;
}
p1[i] = j;
}*/
g.clear();
for (auto &i : gr.edges) {
g.add_edge(cl[i.second], cl[i.first]);
}
gr.clear();
for (auto &i : g.edges) {
gr.add_edge(i.second, i.first);
}
g.prepare();
gr.prepare();
ans.resize(cmp);
/// 1 - rose
/// 0 - violet
for (int i = 0; i < cmp; i++) {
if (w[i] > n) {
int cnt = 0;
color(i);
string answer(3 * n, 'F');
for (int j = 0; j < 3 * n; j++) {
if (ans[cl[j]]) {
answer[j] = 'R';
++cnt;
}
}
if (cnt >= n && cnt <= 2 * n) {
cout << "TAK\n";
cout << answer << '\n';
return;
}
cnt = 0;
ans.assign(cmp, 1);
color1(i);
answer = string(3 * n, 'R');
for (int j = 0; j < 3 * n; j++) {
if (!ans[cl[j]]) {
++cnt;
answer[j] = 'F';
}
}
if (!(cnt >= n && cnt <= 2 * n)) {
cout << "NIE\n";
return;
}
cout << "TAK\n";
cout << answer << '\n';
return;
}
}
order.clear();
used.clear();
used.resize(cmp);
for (int i = 0; i < cmp; i++) {
if (!used[i]) {
dfs(i);
}
}
int s = 0;
for (int v : order) {
s += w[v];
ans[v] = 1;
if (s >= n) {
assert(s <= 2 * n);
break;
}
}
assert(s >= n);
string answer(3 * n, 'F');
int cnt = 0;
for (int i = 0; i < 3 * n; i++) {
if (ans[cl[i]]) {
++cnt;
answer[i] = 'R';
}
}
assert(cnt >= n && cnt <= 2 * n);
cout << "TAK\n";
cout << answer << '\n';
}
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
for (int test = 1; test <= t; test++) {
test_case();
}
}
详细
Test #1:
score: 0
Time Limit Exceeded
input:
2 1 3 1 1 2 2 1 2 3 3 1 1 3 3 1 3 1 1 2 2 2 2 3 3 3 3 1 1