This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define ll long long
#define file(name) \
if(fopen(name".inp", "r")) \
freopen(name".inp", "r", stdin), freopen(name".out", "w", stdout); \
const int MAX = 5e5 + 5;
struct Edge {
int u, v;
int get(int x) {
return x ^ u ^ v;
}
} e[MAX];
int n, m, q;
vector <int> adj[MAX];
namespace sub1 {
bool check() {
return max({n, m, q}) <= 5000;
}
int dd[MAX];
bool solve(int l, int r) {
fill(dd + 1, dd + n + 1, -1);
bool ans = true;
function <void(int, int)>
dfs = [&] (int u, int c) {
dd[u] = c;
for (int i : adj[u]) if(i < l || i > r) {
int v = e[i].get(u);
if(dd[v] == -1) {
dfs(v, 1 ^ c);
} else {
if(c == dd[v]) {
ans = false;
}
}
}
};
for (int u = 1; u <= n; ++u) if(dd[u] == -1) {
dfs(u, 0);
}
return ans;
}
void solve() {
while(q--) {
int l, r; cin >> l >> r;
cout << (solve(l, r) ? "NO" : "YES") << '\n';
}
exit(0);
}
}
struct Query {
int l, r, id;
} queries[MAX];
int ans[MAX];
namespace sub2 {
bool check() {
for (int i = 1; i <= q; ++i) {
if(queries[i].l != 1) {
return false;
}
}
return true;
}
int rank[MAX];
pair <int, int> par[MAX];
bool bipartite[MAX];
void make_set(int v) {
par[v] = make_pair(v, 0);
rank[v] = 0;
bipartite[v] = true;
}
pair <int, int> find_set(int u) {
if(u != par[u].fi) {
int parity = par[u].se;
par[u] = find_set(par[u].fi);
par[u].se ^= parity;
}
return par[u];
}
bool total = true;
bool merge(int a, int b) {
pair <int, int> pa = find_set(a); a = pa.fi; int x = pa.se;
pair <int, int> pb = find_set(b); b = pb.fi; int y = pb.se;
if(a == b) {
if(x == y) {
bipartite[a] = false;
total = false;
}
return false;
}
if(rank[a] < rank[b]) swap(a, b);
par[b] = make_pair(a, 1 ^ x ^ y);
bipartite[a] &= bipartite[b];
if(rank[a] == rank[b]) rank[a]++;
return true;
}
void solve() {
sort(queries + 1, queries + q + 1, [&] (const Query &a, const Query &b) {
return a.r > b.r;
});
int j = m;
for (int i = 1; i <= n; ++i) make_set(i);
for (int i = 1; i <= q; ++i) {
while(j >= 1 && j > queries[i].r) {
merge(e[j].u, e[j].v);
j--;
}
ans[queries[i].id] = total;
}
for (int i = 1; i <= q; ++i) {
cout << (ans[i] ? "NO" : "YES") << '\n';
}
exit(0);
}
}
namespace sub3 {
bool check() {
return true;
}
struct save {
int u, v, ranku, rankv, res, cnt;
};
vector <save> tmp;
int res = true;
int lab[MAX], wei[MAX], dp[MAX];
int find(int u) {
return lab[u] < 0 ? u : find(lab[u]);
}
int get_w(int u) {
return lab[u] < 0 ? 0 : wei[u] ^ get_w(lab[u]);
}
bool merge(int u, int v, int cnt) {
if(!res) return false;
int w = 1 ^ get_w(u) ^ get_w(v);
u = find(u), v = find(v);
assert(u != 0 && v != 0);
if(lab[u] > lab[v]) swap(u, v);
tmp.push_back({u, v, lab[u], lab[v], res, cnt});
if(u == v) {
if(w) res = false;
return w == 0;
}
lab[u] += lab[v];
lab[v] = u;
wei[v] = w;
return true;
}
void rollback(int l, int r) {
if(l > r) return;
while(!tmp.empty() && tmp.back().cnt >= l && tmp.back().cnt <= r) {
auto [u, v, labu, labv, x, _] = tmp.back(); tmp.pop_back();
lab[u] = labu, lab[v] = labv;
wei[v] = 0;
res = x;
}
}
void dnc(int l, int r, int optL, int optR) {
if(l > r) return;
int mid = l + r >> 1;
for (int i = l; i < mid; i++) {
merge(e[i].u, e[i].v, i);
}
int optM = max(mid, optL) - 1;
for (int i = optR; i >= max(mid, optL); --i) {
if(!res) {
optM = i;
break;
}
merge(e[i].u, e[i].v, i);
}
dp[mid] = ++optM;
optM = min(m, optM);
rollback(optM, optR);
merge(e[mid].u, e[mid].v, mid);
dnc(mid + 1, r, optM, optR);
rollback(l, mid);
for (int i = optM + 1; i <= optR; ++i) {
merge(e[i].u, e[i].v, i);
}
dnc(l, mid - 1, optL, optM);
rollback(optM + 1, optR);
}
void solve() {
memset(lab, -1, sizeof lab);
dnc(1, m, 1, m);
for (int i = 1; i <= q; ++i) {
int l = queries[i].l, r = queries[i].r;
cout << (dp[l] > r ? "YES" : "NO") << '\n';
}
}
}
void you_make_it(void) {
cin >> n >> m >> q;
for (int i = 1; i <= m; ++i) {
cin >> e[i].u >> e[i].v;
adj[e[i].u].push_back(i);
adj[e[i].v].push_back(i);
}
// if(sub1::check()) sub1::solve();
for (int i = 1; i <= q; ++i) cin >> queries[i].l >> queries[i].r, queries[i].id = i;
if(sub3::check()) sub3::solve();
}
signed main() {
#ifdef LOCAL
freopen("TASK.inp", "r", stdin);
freopen("TASK.out", "w", stdout);
#endif
file("joker");
auto start_time = chrono::steady_clock::now();
cin.tie(0), cout.tie(0) -> sync_with_stdio(0);
you_make_it();
auto end_time = chrono::steady_clock::now();
cerr << "\nExecution time : " << chrono::duration_cast <chrono::milliseconds> (end_time - start_time).count() << "[ms]" << endl;
return (0 ^ 0);
}
// Dream it. Wish it. Do it.
Compilation message (stderr)
Joker.cpp: In function 'void sub3::dnc(int, int, int, int)':
Joker.cpp:197:15: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
197 | int mid = l + r >> 1;
| ~~^~~
Joker.cpp: In function 'int main()':
Joker.cpp:10:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
10 | freopen(name".inp", "r", stdin), freopen(name".out", "w", stdout); \
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Joker.cpp:261:5: note: in expansion of macro 'file'
261 | file("joker");
| ^~~~
Joker.cpp:10:49: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
10 | freopen(name".inp", "r", stdin), freopen(name".out", "w", stdout); \
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
Joker.cpp:261:5: note: in expansion of macro 'file'
261 | file("joker");
| ^~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |