\(\text{Solution}\)

很好的想法是用平面图欧拉定理 \(E=V+F-2\)
那么就要解决的问题是环内的边数与面数
科技的使用:平面图转对偶图
建图过程大概就是将每条无向边拆成两条双向边,考虑找出所有按逆时针方向围成的最小面
那么这个只需要考虑每条的下一条边是谁,极角排序即可
把面当点,点的权值为围成它的边数,两面若在原图中右边,则对偶图中对应点连边,那么相当于原图中的边会割到新图中的边

然后随意找棵生成树,维护子树信息
发现询问就是框住了一个生成树的连通块,那么绕环走一圈,找到环上每条边对应的两个面,相应加减信息即可

\(\text{Code}\)

#include <bits/stdc++.h>
#define eb emplace_back
using namespace std;

template<typename Tp>
void read(Tp &x) {
    x = 0; char ch = getchar(); int f = 0;
    for(; !isdigit(ch); f |= (ch == '-'), ch = getchar());
    for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
    if (f) x = ~x + 1;
}

typedef double db;
typedef long long LL;
const db eps = 1e-10;
const int N = 1200005;
int n, m, b[N];

struct Vector{
	int x, y;
	Vector(int xx = 0, int yy = 0){x = xx, y = yy;}
	Vector operator - (const Vector &B){return Vector(x - B.x, y - B.y);}
	LL operator * (const Vector &B){return ((LL)x * B.y - (LL)y * B.x);}
}a[N];

int tot = 1, nxt[N], rt, cov[N], sz[N], val[N], fa[N], bz[N], eg[N][2];
vector<int> G[N];

struct edge {
    int q, p, id; db k;
    bool operator < (const edge &b) const {return fabs(k - b.k) < eps ? (p < b.p) : (k < b.k);}
}e[N << 1];
vector<edge> E[N];

void add(int u, int v) {
    ++tot, e[tot] = edge{u, v, tot, atan2(a[v].y - a[u].y, a[v].x - a[u].x)}, E[u].eb(e[tot]);
}
void build() {
    for(int i = 1; i <= n; i++) sort(E[i].begin(), E[i].end());
    for(int i = 2; i <= tot; i++) {
        auto it = lower_bound(E[e[i].p].begin(), E[e[i].p].end(), e[i ^ 1]);
        if (it == E[e[i].p].begin()) it = E[e[i].p].end();
        nxt[i] = (*prev(it)).id;
    }
    int cnt = 0;
    for(int i = 2; i <= tot; i++) {
        if (cov[i]) continue;
        cov[i] = ++cnt, val[cnt] = 1; LL S = 0;
        for(int j = nxt[i]; j != i; cov[j] = cnt, ++val[cnt], j = nxt[j])
            S += (a[e[j].q] - a[e[i].q]) * (a[e[j].p] - a[e[i].q]);
        if (S <= 0) rt = cnt, fa[rt] = rt;
    }
    for(int i = 2; i <= tot; i++) G[cov[i]].eb(i);
}

int Q[N];
void bfs() {
    int head = 0, tail = 1; Q[1] = rt;
    while (head < tail) {
        int u = Q[++head]; sz[u] = 1;
        for(auto k : G[u]) {
            int v = cov[k ^ 1]; if (fa[v]) continue;
            fa[v] = u, bz[k] = bz[k ^ 1] = 1, Q[++tail] = v;
        }
    }
    for(int i = tail, u; i > 1; i--) u = Q[i], sz[fa[u]] += sz[u], val[fa[u]] += val[u];
}

int main() {
    freopen("graph.in", "r", stdin);
    freopen("graph.out", "w", stdout);
    read(n), read(m);
    for(int i = 1, x, y; i <= m; i++) read(eg[i][0]), read(eg[i][1]);
    for(int i = 1, x, y; i <= n; i++) read(x), read(y), a[i] = Vector(x, y);
    for(int i = 1; i <= m; i++) add(eg[i][0], eg[i][1]), add(eg[i][1], eg[i][0]);
    build(), bfs();
    int qq; read(qq);
    for(; qq; qq--) {
        int K; read(K);
        for(int j = 1, x; j <= K; j++) read(b[j]);
        int vE = 0, vF = 0;
        for(int j = 1; j <= K; j++) {
            int q = b[j], p = b[j % K + 1];
            auto it = lower_bound(E[q].begin(), E[q].end(), edge{q, p, 0, atan2(a[p].y - a[q].y, a[p].x - a[q].x)});
            int id = (*it).id; if (!bz[id]) continue;
            if (fa[cov[id]] == cov[id ^ 1]) vE += val[cov[id]], vF += sz[cov[id]];
            else vE -= val[cov[id ^ 1]], vF -= sz[cov[id ^ 1]];
        }
        vE = (abs(vE) + K) >> 1, vF = abs(vF) + 1, printf("%d\n", vE + 2 - vF);
    }
}