이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <iostream>
#include <vector>
#include <stack>
#include <cassert>
using namespace std;
bool DBG = 1;
void asrt(bool b)
{
if(!b)
{
cerr << "failed!\n";
while(1);
}
}
struct disjoint_set
{
int N;
vector<int> parent;
vector<int> parent_edge; //xor
vector<int> subtree;
stack<int> ops;
stack<bool> bipartite;
stack< stack<int> > compress_node;
stack< stack<int> > prev_parent;
stack< stack<int> > prev_toggle;
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 compress(int u)
{
bool toggle = 0;
int v = u;
for(v = u; parent[v] != v; v = parent[v])
{
toggle ^= parent_edge[v];
}
if(v == parent[u] || v == u)
{
compress_node.top().push(-1);
prev_parent.top().push(-1);
prev_toggle.top().push(-1);
}
else
{
compress_node.top().push(u);
prev_parent.top().push(parent[u]);
prev_toggle.top().push(parent_edge[u]);
parent[u] = v;
parent_edge[u] = toggle;
}
}
void decompress()
{
int u = compress_node.top().top();
int v = prev_parent.top().top();
int t = prev_toggle.top().top();
asrt(!compress_node.empty());
asrt(!prev_parent.empty());
asrt(!prev_toggle.empty());
asrt(!compress_node.top().empty());
asrt(!prev_parent.top().empty());
asrt(!prev_toggle.top().empty());
compress_node.top().pop();
prev_parent.top().pop();
prev_toggle.top().pop();
if(t != -1)
{
parent[u] = v;
parent_edge[u] = t;
}
}
int root(int u)
{
while(parent[u] != u)
u = parent[u];
return u;
}
void join(int u, int v)
{
// cerr << "join " << u << ' ' << v << '\n';
int opp = 1;
compress_node.push(stack<int>{});
prev_parent.push(stack<int>{});
prev_toggle.push(stack<int>{});
compress(u);
compress(v);
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()
{
// cerr << "rollback\n";
int u = ops.top();
ops.pop();
bipartite.pop();
subtree[ parent[u] ] -= subtree[u];
parent[u] = u;
parent_edge[u] = 0;
while(!(compress_node.top()).empty())
{
decompress();
}
asrt(!compress_node.empty());
asrt(!prev_parent.empty());
asrt(!prev_toggle.empty());
compress_node.pop();
prev_parent.pop();
prev_toggle.pop();
}
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, 0);
//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]);
}
bool flag = 0;
void solve(int l1, int l2, int r1, int r2) // [L, R] == [l1, r2] at the beginning
{
// cerr << "solve " << l1 << ' ' << l2 << ' ' << r1 << ' ' << r2 << '\n';
bool F = 0;
if(l1 <= 8 && 8 <= l2) F = 1;
// assert(L == l1);
// assert(R == r2);
int lmid = (l1+l2)/2;
int rmid;
flag = 0;
// dbg(lmid);
// cerr << "hello\n";
// if(F) cerr << "special solve " << l1 << ' ' << l2 << ' ' << r1 << ' ' << r2 << '\n';
if(!DSU.is_bipartite())
{
if(DBG) while(1);
// if(F) cerr << "!!!!\n";
// if(!F)
// {
// cerr << L << ' ' << R << '\n';
// cerr << "???????\n";
//
//
// cerr << "###\n";
//
//
// cerr << "DSU: ";
// for(int i = 1; i <= N; i++) cerr << DSU.root(i) << ' ';
// cerr << '\n';
// }
// cerr << "check\n";
// cerr << l1 << ' ' << l2 << " emergency\n";
// cerr << lmid << '\n';
// cerr << "M = " << M << '\n';
for(int i = lmid; i <= l2; i++)
{
minR[i] = M+1;
// cerr << minR[i] << '\n';
}
if(l1 <= lmid-1)
{
solve(l1, lmid-1, r1, r2); //ADJUST L AND R!!!!! -> not necessary
}
return;
}
// cerr <<
// for(int i = 1; i <= N; i++) dbg(to_string(i), DSU.root(i));
// dbg(DSU.is_bipartite());
while(L < lmid)
{
if(DBG) while(1);
contract_left();
}
// if(F)cerr<<"lmid="<<lmid<<"\n";
if(!DSU.is_bipartite())
{
if(DBG) while(1);
while(l1 < L)
expand_left();
// cerr << "check\n";
// cerr << l1 << ' ' << l2 << " emergency\n";
// cerr << lmid << '\n';
// cerr << "M = " << M << '\n';
for(int i = lmid; i <= l2; i++)
{
minR[i] = M+1;
// cerr << minR[i] << '\n';
}
if(l1 <= lmid-1)
{
solve(l1, lmid-1, r1, r2); //ADJUST L AND R!!!!! -> not necessary
}
return;
}
// if(F) cerr << "check\n";
rmid = r2;
while(DSU.is_bipartite())
{
// cerr << "bipartite = yes\n";
rmid = min(rmid, R);
contract_right();
}
// cerr << "rmid = " << rmid << '\n';
minR[lmid] = rmid;
while(R < r2)
expand_right();
while(l1 < L)
expand_left();
// assert(L == l1 && R == r2);
if(l1 <= lmid-1)
{
if(DBG) while(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)
{
if(DBG) while(1);
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()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
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 <= Q; u++)
{
cin >> x >> x;
cout << "NO\n";
}
return 0;
}
L = 1;
R = M;
if(N+M+Q > 6000)
while(1);
solve(1, M, 1, M);
// for(int j = 1; j <= M; j++) cerr << minR[j] << ' ';
// cerr << '\n';
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
}
}
컴파일 시 표준 에러 (stderr) 메시지
Joker.cpp: In function 'void solve(int, int, int, int)':
Joker.cpp:235:10: warning: variable 'F' set but not used [-Wunused-but-set-variable]
235 | bool F = 0;
| ^| # | 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... |