F题
首先考虑将状态用一个串表示。
对于每个灯,将按下它的同时改变的所有灯的下标置1,其他的置0.
用表示的取反。题目的要求就转化为,用这些串异或组合出.
线性基维护即可。由于位,选择用bitset或者用两个long long的数字维护线性基。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int long long
#define endl '\n'
const int B = 100;
struct liner_base {
vector<bitset<101>> a;
vector<vector<int>> b;
int cnt = 0;
liner_base() {
a.resize(B + 1);
b.resize(B + 1);
}
int insert(bitset<101> x, int id) {
vector<int> v = { id };
for (int i = B;i >= 0;i--) {
if (x[i]) {
if (a[i].count() == 0) {
a[i] = x;
b[i] = v;
cnt++;
return 1;
}
else {
x ^= a[i];
for (auto y : b[i]) v.push_back(y);
}
}
}
return 0;
}
int size() {
return cnt;
}
vector<int> ask(bitset<101> x) {
vector<int> res;
for (int i = B;i >= 0;i--) {
if (x[i]) {
x ^= a[i];
for (auto y : b[i]) res.push_back(y);
}
}
if (x.count() != 0) {
res.clear();
}
return res;
}
};
void Prework() {
}
void Solve() {
int n;cin >> n;
string s;cin >> s;s = ' ' + s;
map<int, vector<int>> X, Y;
vector<array<int, 2>> a(n + 1);
for (int i = 1;i <= n;i++) {
int x, y;cin >> x >> y;
X[x].push_back(i);
Y[y].push_back(i);
a[i] = { x,y };
}
bitset<101> dp;
liner_base lb;
for (int i = 1;i <= n;i++) {
auto [x, y] = a[i];
dp.reset();
for (auto u : X[x]) {
dp[u] = 1;
}
for (auto u : Y[y]) {
dp[u] = 1;
}
lb.insert(dp, i);
}
bitset<101> tar;
for (int i = 1;i <= n;i++) {
if (s[i] == '0') tar[i] = 1;
}
if (count(s.begin() + 1, s.end(), '1') == n) return cout << "0\n", void();
auto res = lb.ask(tar);
if (res.size() == 0) {
cout << "-1\n";
}
else {
vector<int> ans(n + 1);
for (auto i : res) ans[i] ^= 1;
int sum = 0;
for (int i = 1;i <= n;i++) {
if (ans[i]) sum += 1;
}
cout << sum << endl;
for (int i = 1;i <= n;i++) {
if (ans[i]) cout << i << " ";
}
cout << endl;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T = 1;
//cin >> T;
Prework();
while (T--) Solve();
}