列表

详情


NC231637. 送你一张DAG

描述

Jason有一个神奇的有向图,除了1号点以外,每个点i到中每个点有一条单向边,其中
某天,Jason找了Emma陪他玩游戏。具体地说,他们在图上的某些点各放一个棋子,并拿来了几瓶ad钙奶(也可以不拿)。每次操作要么把某个棋子按所在位置的出边移动一次,要么取走任意数量的ad钙奶。Jason和Emma轮流进行操作,Jason先手。不能操作的人就输了。
他们玩了很多局,每一局Jason会先放棋子,然后Emma决定拿来多少ad钙奶。Jason和Emma都会采取最优策略(Jason居然敢不放水?),Emma想获得胜利,请你每局告诉她,她该拿来多少ad钙奶。

输入描述

第一行一个正整数n,代表节点数,
接下来n-1行每行两个正整数L_i, R_i
接下来一行一个正整数q,表示进行的局数,
接下来q行,每行第一个正整数为m,接下来m个正整数,代表这些节点上有棋子。

输出描述

q行,每行一个整数,代表Emma应该在旁边放多少瓶ad钙奶。

示例1

输入:

10
1 1
1 2
2 2
4 4
3 3
2 6
3 5
3 3
4 5
3
2 6 3
4 8 5 2 1
1 2

输出:

2
3
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 1612ms, 内存消耗: 4200K, 提交时间: 2021-12-08 23:16:20

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

const int N = 2e5 + 5;

struct node {
	int l, r, id;
	node() {}
	node(int lx, int rx, int idx) {l = lx, r = rx, id = idx;}
};
node rec[N];
bool cmp(node a, node b) {
	if (a.r == b.r) return a.l < b.l;
	else return a.r < b.r;
}
int sg[N], n, m, cnt[N], now_sg, l = 1, r = 0;

void rm(int pos) {
	int now = sg[pos];
	cnt[now]--;
	if (cnt[now] == 0)  now_sg = min(now_sg, now);
}

void add(int pos) {
	int now = sg[pos];
	cnt[now]++;
	while (cnt[now_sg]) now_sg++;
}

int main(void) {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n;
	for (int i = 1; i < n; i++) {
		cin >> rec[i].l >> rec[i].r;
		rec[i].id = i + 1;
	}
	sort(rec + 1, rec + n, cmp);
	for (int i = 1; i < n; i++) {
		int ql = rec[i].l, qr = rec[i].r, qid = rec[i].id;
		while (r < qr) add(++r);
		while (l > ql) add(--l);
		while (r > qr) rm(r--);
		while (l < ql) rm(l++);
		sg[qid] = now_sg;
	}
	cin >> m;
	for (int i = 1, x, v; i <= m; i++) {
		int ans = 0;
		cin >> x;
		for (int j = 1; j <= x; j++) {
			cin >> v;
			ans ^= sg[v];
		}
		cout << ans << '\n';
	}
	return 0;
}

上一题