// TROOT, Setter's solution #include #include #include using namespace std; #define mod 1000000007 #define maxn 200005 struct node { int l, r, mx, add, tag; } tree[maxn * 4]; int n, m, i, j, timer, tin[maxn], tout[maxn], f[maxn], t[maxn], p[maxn], inv[maxn], up[maxn][17], was[maxn], cha, x, y, present, q, ii, nextv; char ch; void addedge(int x, int y) { // adding an edge ++ii; t[ii] = y; p[ii] = f[x]; f[x] = ii; } bool anc (int x, int y) { // checking whether x is an ancestor of y using input/output time approach return (tin[x] <= tin[y] && tout[y] <= tout[x]); } int lca (int x, int y) { // finding the LCA if (anc(x, y)) return x; for(int i = 16; i >= 0; i--) if (!anc(up[x][i], y)) x = up[x][i]; return up[x][0]; } void dfs (int k) { // DFS for finding input/output times and preparing the LCA tin[k] = ++timer; // input time inv[timer] = k; was[k] = 1; int q = f[k]; while (q > 0) { if (!was[t[q]]) { up[t[q]][0] = k; for(i = 1; i < 17; i++) up[t[q]][i] = up[up[t[q]][i - 1]][i - 1]; dfs(t[q]); } q = p[q]; } tout[k] = ++timer; // output time inv[timer] = 1; } void init (int pos, int l, int r) { // segment tree preparation tree[pos].l = l, tree[pos].r = r; if (l < r) { init(pos + pos, l, (l + r) >> 1); init(pos + pos + 1, ((l + r) >> 1) + 1, r); tree[pos].tag = (tree[pos + pos].tag * 1LL * tree[pos + pos + 1].tag) % mod; } else tree[pos].tag = inv[l]; } void modify (int pos, int l, int r, int x) { // segment tree modification if (tree[pos].l == l && tree[pos].r == r) tree[pos].add += x; else { if (l <= min(r, tree[pos + pos].r)) modify(pos + pos, l, min(r, tree[pos + pos].r), x); if (max(l, tree[pos + pos + 1].l) <= r) modify(pos + pos + 1, max(l, tree[pos + pos + 1].l), r, x); tree[pos].mx = max(tree[pos + pos].mx + tree[pos + pos].add, tree[pos + pos + 1].mx + tree[pos + pos + 1].add); tree[pos].tag = 1; if (tree[pos].mx == tree[pos + pos].mx + tree[pos + pos].add) tree[pos].tag = (tree[pos].tag * 1LL * tree[pos + pos].tag) % mod; if (tree[pos].mx == tree[pos + pos + 1].mx + tree[pos + pos + 1].add) tree[pos].tag = (tree[pos].tag * 1LL * tree[pos + pos + 1].tag) % mod; } } int main (int argc, char * const argv[]) { scanf("%d %d", &n, &m); for(i = 1; i < n; i++) { scanf("%d %d", &x, &y); addedge(x, y); addedge(y, x); } for(i = 0; i < 17; i++) up[1][i] = 1; dfs(1); init(1, 1, n + n); for(i = 1; i <= m; i++) { ch = getchar(); while (ch != '+' && ch != '-') ch = getchar(); if (ch == '+') cha = 1; else cha = -1; // +1 for adding, -1 for deleting scanf("%d %d", &x, &y); q = lca(x, y); if (q == x || q == y) { // consider two cases - when q is from {x, y} if (anc(y, x)) swap(x, y); nextv = y; for(j = 16; j >= 0; j--) if (!anc(up[nextv][j], x)) nextv = up[nextv][j]; modify(1, tin[y], tout[y], cha); if (tin[nextv] != 1) modify(1, 1, tin[nextv] - 1, cha); if (tout[nextv] != n * 2) modify(1, tout[nextv] + 1, n * 2, cha); } else { // and when it is not modify(1, tin[x], tout[x], cha); modify(1, tin[y], tout[y], cha); } present += cha; if (present == tree[1].mx + tree[1].add) printf("%d\n", tree[1].tag); else printf("%d\n", -1); } return 0; }