#include <bits/stdc++.h>
typedef long long ll;
using std::sort;
using std::swap;
using std::min; using std::max;
#define l(p) tree[p].l
#define r(p) tree[p].r
#define s(p) tree[p].sum
#define ls(p) tree[p].lson
#define rs(p) tree[p].rson
#define INF INT_MAX
#define rd() read<int>()
#define E(i, l, r) for (int i = l; i <= r; ++ i)
template <typename T>
inline T read() {
T x = 0; bool f = 0; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = 1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return f ? -x : x;
}
const int N = 2e5 + 5;
int n, m, q;
int root[N * 2], cnt;
int gg[N * 2];
struct Tree {
int idx, cnt;
int val[N * 2];
int h[N * 2];
int fa[N * 2];
int an[N * 2][30];
int e[N * 4], ne[N * 4];
int cal, dfn[N * 4], sts[N * 4][2];
Tree () {
idx = 0;
cnt = n;
E(i, 1, n * 2)
fa[i] = i;
memset(h, -1, sizeof h);
memset(an, 0, sizeof an);
memset(val, 0, sizeof val);
}
void clear() {
idx = 0;
cnt = n;
E(i, 1, n * 2)
fa[i] = i;
memset(h, -1, sizeof h);
memset(an, 0, sizeof an);
memset(val, 0, sizeof val);
}
int getfa(int x) {
if (x == fa[x]) return x;
return fa[x] = getfa(fa[x]);
}
void add(int x, int y) {
ne[idx] = h[x];
e[idx] = y;
h[x] = idx ++;
// std::cout << x << ' ' << h[x] << '\n';
}
void dfs(int cur, int fa) {
if (cur <= n) {
dfn[++ cal] = cur;
sts[cur][0] = cal;
}
else
sts[cur][0] = INF;
E(i, 1, 20)
an[cur][i] = an[an[cur][i - 1]][i - 1];
// std::cout << cur << ' ' << fa << ' ' << h[cur] << "a\n";
for (int i = h[cur]; ~i; i = ne[i]) {
// std::cout << cur << ' ' << fa << ' ' << e[i] << '\n';
int go = e[i];
if (go == fa) continue;
// std::cout << cur << ' ' << go << ' ' << val[go] << '\n';
dfs(go, cur);
sts[cur][0] = min(sts[cur][0], sts[go][0]);
}
sts[cur][1] = cal;
// std::cout << cur << 'c' << sts[cur][0] << ' ' << sts[cur][1] << '\n';
}
} Kti, Kta;
struct Node {
int l, r;
int lson, rson;
int sum;
} tree[N * 8];
struct Edge {
int x, y;
} edgeset[N];
bool cmpMin(Edge lhs, Edge rhs) {
return lhs.y < rhs.y;
}
bool cmpMax(Edge lhs, Edge rhs) {
return lhs.x > rhs.x;
}
void KruskalMin() {
Kti.clear();
sort(edgeset + 1, edgeset + m + 1, cmpMin);
for (int i = 1; i <= m; ++ i) {
Edge cur = edgeset[i];
int u = cur.x, v = cur.y;
int x = Kti.getfa(u), y = Kti.getfa(v);
if (x != y) {
Kti.val[++ Kti.cnt] = v;
// std::cout << u << ' ' << v << ' ' << x << ' ' << y << ' ' << Kti.cnt << ' ' << Kti.fa[Kti.cnt] << '\n';
Kti.add(x, Kti.cnt); Kti.add(Kti.cnt, x);
Kti.add(y, Kti.cnt); Kti.add(Kti.cnt, y);
Kti.fa[x] = Kti.fa[y] = Kti.cnt;
Kti.an[x][0] = Kti.an[y][0] = Kti.cnt;
}
}
Kti.dfs(Kti.cnt, 0);
}
void KruskalMax() {
Kta.clear();
sort(edgeset + 1, edgeset + m + 1, cmpMax);
for (int i = 1; i <= m; ++ i) {
Edge cur = edgeset[i];
int u = cur.x, v = cur.y;
int x = Kta.getfa(u), y = Kta.getfa(v);
if (x != y) {
Kta.val[++ Kta.cnt] = u;
// std::cout << u << ' ' << v << ' ' << x << ' ' << y << ' ' << cnt << ' ' << Kta.fa[cnt] << '\n';
Kta.add(x, Kta.cnt); Kta.add(Kta.cnt, x);
Kta.add(y, Kta.cnt); Kta.add(Kta.cnt, y);
Kta.fa[x] = Kta.fa[y] = Kta.cnt;
Kta.an[x][0] = Kta.an[y][0] = Kta.cnt;
}
}
Kta.dfs(Kta.cnt, 0);
}
void build(int p, int l, int r) {
cnt = max(cnt, p);
l(p) = l; r(p) = r; s(p) = 0;
// std::cout << p << ' ' << l << ' ' << r <<'\n';
if (l == r) return;
int mid = l + r >> 1;
ls(p) = p << 1; rs(p) = ls(p) + 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
}
void insert(int cur, int last, int x) {
// std::cout << cur << ' ' << last << ' ' << x << ' ' << l(last) << ' ' << r(last) << '\n';
l(cur) = l(last); r(cur) = r(last);
s(cur) = s(last) + 1;
if (l(last) == r(last)) return;
int mid = (l(cur) + r(cur)) / 2;
if (x <= mid) {
rs(cur) = rs(last);
ls(cur) = ++ cnt;
insert(ls(cur), ls(last), x);
}
else {
ls(cur) = ls(last);
rs(cur) = ++ cnt;
insert(rs(cur), rs(last), x);
}
}
int query(int lt, int rt, int l, int r) {
// std::cout << l(lt) << 'q' <<r(lt) << ' ' << s(lt) << ' ' << s(rt) << '\n';
if (l(lt) > r || r(lt) < l) return 0;
if (l <= l(lt) && r(lt) <= r) return s(rt) - s(lt);
return query(ls(lt), ls(rt), l, r) + query(rs(lt), rs(rt), l, r);
}
int main() {
n = rd();
m = rd();
q = rd();
E(i, 1, m) {
int x, y;
x = rd(); y = rd();
++ x; ++ y;
if (x > y) swap(x, y);
edgeset[i] = {x, y};
}
KruskalMin();
KruskalMax();
E(i, 1, n)
gg[i] = Kta.sts[Kti.dfn[i]][0];
// E(i, 1, n)
// std::cout << Kti.dfn[i] << ' ';
// puts("");
// E(i, 1, n)
// std::cout << Kta.dfn[i] << ' ';
// puts("");
// E(i, 1, n)
// std::cout << gg[i] << ' ';
// puts("");
build(1, 1, n); root[0] = 1;
E(i, 1, Kti.cnt) {
root[i] = ++ cnt;
insert(root[i], root[i - 1], gg[i]);
}
Kti.val[0] = INF;
while (q --) {
int s, t, L, R;
s = rd(); t = rd();
L = rd(); R = rd();
++ s; ++ t;
++ L; ++ R;
for (int i = 20; i >= 0; -- i)
if (Kta.val[Kta.an[s][i]] >= L)
s = Kta.an[s][i];
for (int i = 20; i >= 0; -- i)
if (Kti.val[Kti.an[t][i]] <= R)
t = Kti.an[t][i];
int l1, r1, l2, r2;
l1 = Kta.sts[s][0];
r1 = Kta.sts[s][1];
l2 = Kti.sts[t][0];
r2 = Kti.sts[t][1];
// std::cout << s << ' ' <<t << ' ' << l1 << ' ' << r1 << ' ' << l2 << ' ' << r2 <<'\n';
if (query(root[l2 - 1], root[r2], l1, r1) > 0)
printf("1\n");
else printf("0\n");
}
return 0;
}
RE处为主席树query,原因不清楚