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 <iostream>
#include <vector>
#include <stack>
#include <cassert>
using namespace std;
struct disjoint_set
{
int N;
vector<int> parent;
vector<int> parent_edge;
vector<int> subtree;
stack<int> ops;
stack<bool> bipartite;
disjoint_set()
{
;
}
disjoint_set(int N_)
{
N = N_;
parent = vector<int>(1+N);
parent_edge = vector<int>(1+N);
subtree = vector<int>(1+N);
for(int i = 0; i <= N; i++)
{
parent[i] = i;
parent_edge[i] = 0;
subtree[i] = 1;
}
ops.push(0);
bipartite.push(1);
}
void join(int u, int v)
{
int opp = 1;
while(u != parent[u])
{
opp ^= parent_edge[u];
u = parent[u];
}
while(v != parent[v])
{
opp ^= parent_edge[v];
v = parent[v];
}
if(u == v)
{
ops.push(0);
if(bipartite.top())
{
if(opp == 0) bipartite.push(1);
else bipartite.push(0);
}
else bipartite.push(0);
}
else
{
if(subtree[u] < subtree[v]) swap(u, v);
parent[v] = u;
parent_edge[v] = opp;
subtree[u] += subtree[v];
ops.push(v);
bipartite.push( bipartite.top() );
}
}
void rollback()
{
int u = ops.top();
ops.pop();
bipartite.pop();
subtree[ parent[u] ] -= subtree[u];
parent[u] = u;
parent_edge[u] = 0;
}
bool is_bipartite()
{
return bipartite.top();
}
};
const int maxN = 200'000;
const int maxM = 200'000;
int N, M, Q;
vector<int> u(1+maxM), v(1+maxM);
vector<int> minR(1+maxN);
//the minimum value of R so that if the roads i, ... R are blocked the graph is bipartite
disjoint_set DSU;
int L;
int R;
void expand_right()
{
R++;
DSU.rollback();
}
void contract_right()
{
R--;
DSU.join(u[R+1], v[R+1]);
}
void expand_left()
{
L--;
DSU.rollback();
}
void contract_left()
{
L++;
DSU.join(u[L-1], v[L-1]);
}
void solve(int l1, int l2, int r1, int r2) // [L, R] == [l1, r2] at the beginning
{
assert(L == l1);
assert(R == r2);
int lmid = (l1+l2)/2;
int rmid;
if(!DSU.is_bipartite())
{
for(int i = lmid; i <= l2; i++)
minR[i] = M+1;
if(l1 <= lmid-1)
{
solve(l1, lmid-1, r1, r2); //ADJUST L AND R!!!!! -> not necessary
}
}
while(L < lmid)
contract_left();
rmid = r2;
while(DSU.is_bipartite())
{
rmid = min(rmid, R);
contract_right();
}
minR[lmid] = rmid;
while(R < r2)
expand_right();
while(l1 < L)
expand_left();
assert(L == l1 && R == r2);
if(l1 <= lmid-1)
{
while(rmid < R)
contract_right();
assert(L == l1 && R == rmid);
solve(l1, lmid-1, r1, rmid);
while(R < r2)
expand_right();
}
if(lmid+1 <= l2)
{
while(L < lmid+1)
contract_left();
assert(L == lmid+1 && R == r2);
solve(lmid+1, l2, rmid, r2);
while(l1 < L)
expand_left();
}
assert(L == l1 && R == r2);
}
int main()
{
cin >> N >> M >> Q;
for(int j = 1; j <= M; j++) cin >> u[j] >> v[j];
DSU = disjoint_set(N);
disjoint_set temp(N);
for(int j = 1; j <= M; j++) temp.join(u[j], v[j]);
if(temp.is_bipartite())
{
int x;
for(int u = 1; u <= 2*Q; u++) cin >> x;
for(int u = 1; u <= Q; u++) cout << "NO\n";
}
L = 1;
R = M;
solve(1, M, 1, M);
for(int q = 1; q <= Q; q++)
{
int l, r;
cin >> l >> r;
if(minR[l] <= r) cout << "NO\n"; //bipartite
else cout << "YES\n"; //not bipartite
}
}
| # | 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... |