题目链接:http://hihocoder.com/problemset/problem/1114?sid=860881
此题需要注意:
只需要试第一格是否为雷就可以通过数据算出后面是否为雷。
所以只用试两次,
第一次把一格设为雷,算出后面的情况;第二次把第一格设为不是雷,算出后面的情况。
若两次都算出来了,则将两次的情况对比,没有变化的部分就是答案。
若只有一次满足条件,则那一次直接就是答案。
#include<iostream>
#include<vector>
const int N=100005;
int arr[N];
int ans[2][N]; //此变量的作用是存储两次情况
using namespace std;
bool isRight(int len, int channel) {
int left = 0, mid = channel, right = 0;
for (int i = 0; i < len; i++) {
ans[channel][i] = mid;
right = arr[i] - left - mid;
if (right < 0 || right>1)return false;
left = mid; mid = right;
}
if (right)return false;
return true;
}
int main() {
int n;cin >> n;
while (n--) {
int len;cin >> len;
for (int i = 0; i < len; i++)
cin >> arr[i];
vector<int> ones; vector<int> zeros; //存储位置信息
int flag1 = isRight(len, 0); //将第一个位置设为不是雷
int flag2 = isRight(len, 1); //设为雷
int cnt1 = 0, cnt2 = 0;
int ch = flag1 ? 0 : 1;
for (int i = 0; i < len; i++) { //如果两种情况都为真,则没有变化的部分将进入判断条件,此时能判断是否为雷
if (ans[0][i] == ans[1][i] || !flag1 || !flag2) { //如果只有一种情况为真,则其一定是正确的情况
if (ans[ch][i]) {
cnt1++;
ones.push_back(i + 1);
}
else {
cnt2++;
zeros.push_back(i + 1);
}
}
}
cout << cnt1;
for (auto i : ones)cout << ' ' << i;
cout << endl;
cout << cnt2;
for (auto i : zeros)cout << ' ' << i;
cout << endl;
}
return 0;
}