传送门:QAQ
题意:给你一个长度为n的01串,每次操作可以反转间隔相等的三个数字,问你是否能在[n/3]+12的次数内将串全部变为0,若可以,则输出操作,否则输出NO
思路:%大佬的题解后,才懂了一点点。
首先我们要在[n/3]+12的次数内做完,我们只要保证每次操作都能确保三个数变为0(之后不会改变),这样我们就可以确定次数满足题目的要求
其次,进行分类讨论,具体看代码,我觉得我写的一般人都看得懂。小范围的时候要暴力的反转,只要枚举哪些操作然后进行反转,就可以得到答案
附上代码:
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<pair<int, int>>q;
int ax[100010];
int bn[100010];
int n;
int anns;
struct inst {
int x, y, z;
};
vector<inst>gx;
int end(int l, int r) {
for (int i = l; i <= r; i++) if (bn[i]) return false;
return true;
}
void revers(int a, int b, int c) {
ax[a] = !ax[a]; ax[b] = !ax[b]; ax[c] = !ax[c];
inst xx;
xx.x = a;
xx.y = b;
xx.z = c;
gx.push_back(xx);
}
void revers2(int a, int b, int c) {
bn[a] = !bn[a]; bn[b] = !bn[b]; bn[c] = !bn[c];
}
void solve0(int left, int r) {
q.clear();
for (int i = left; i <= r - 2; i++) {
for (int j = i + 2; j <= r; j += 2) {
q.push_back(make_pair(i, j));
}
}
int u = 1 << q.size();
for (int i = 0; i <u; i++) {
for (int j = left; j <= r; j++) bn[j] = ax[j];
for (int j = 0; j < q.size(); j++) {
if (i & 1 << j) {
revers2(q[j].first, (q[j].first + q[j].second) / 2, q[j].second);
}
}
if (end(left, r)) {
anns = true;
for (int j = 0; j < q.size(); j++) if (i & 1 << j) {
revers(q[j].first, (q[j].first+ q[j].second)/2,q[j].second);
}
return;
}
}
}
void solve1(int left,int r) {
while (r - left + 1 < 8) {
while (r - left + 1 <= 8 && left >= 1) left--;
while (r - left + 1 <= 8 && r < n - 1) r++;
solve0(left, r);
return;
}
if (ax[left] == 0) {
solve1(left + 1, r);
return;
}
if (ax[r] == 0) {
solve1(left, r - 1);
return;
}
if (ax[left] == 1 && ax[left+1] == 1 && ax[left+2] == 1) {
revers(left, left + 1, left + 2);
solve1(left + 3, r);
return ;
}
if (ax[left] == 1 && ax[left + 1] == 0 && ax[left + 2] == 1) {
revers(left, left + 2, left + 4);
solve1(left + 3, r);
return;
}
if (ax[left] == 1 && ax[left + 1] == 0 && ax[left + 2] == 0) {
revers(left, left + 3, left + 6);
solve1(left + 3, r);
return;
}
if (ax[r] == 1 && ax[r - 1] == 1 && ax[r - 2] == 1) {
revers(r, r - 1, r - 2);
solve1(left, r-3);
return;
}
if (ax[r] == 1 && ax[r - 1] == 0 && ax[r - 2] == 1) {
revers(r, r - 2, r - 4);
solve1(left, r - 3);
return;
}
if (ax[r] == 1 && ax[r - 1] == 0 && ax[r - 2] == 0) {
revers(r, r - 3, r - 6);
solve1(left, r - 3);
return;
}
if (ax[left] == 1 && ax[left + 1] == 1 && ax[left + 2] == 0) {
if ((left + r+1) %2== 1) {
int mid = (left + r) / 2;
revers(left, mid , r);
revers(left+1, mid, r-1);
solve1(left + 3, r - 3);
}
if ((left + r+1) % 2 == 0) {
revers(left, (left + r - 1) / 2, r-1);
revers(left+1, (left + r + 1) / 2, r );
solve1(left + 3, r - 3);
}
return ;
}
}
int main(void) {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &ax[i]);
}
anns = 0;
solve1(0, n - 1);
if (anns) {
printf("YES\n");
printf("%d\n", gx.size());
for (int i = 0; i < gx.size(); i++) {
printf("%d %d %d\n", gx[i].x+1, gx[i].y+1, gx[i].z+1);
}
}
else printf("NO\n");
}