分析
重点是查询部分,可以从性质入手,首先只有1和2,那么也就是可以根据奇偶来判断,通过改变1的数量来进行判断可不可以实现区间和的存在,假如查询的和是一个奇数,此时如果有奇数个1,那么只要数组的和大于等于查询的区间和,就一定可以实现此区间和,因为每次数组可以从两边选,要么删去一个2,要么删去两边的1,总会达到查询的区间和;如果有偶数个1,那么需要删去一个1,也就是删去最后一个1的之前的区间和或者删去第一个1的之后的区间和,这两段区间和其中只要存在大于等于查询的区间和,同上面一样,只要奇偶性一样就可以进行减二或者删去两个1操作,查询的值是偶数时也类似上面思想。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve() {
int n, q;
cin >> n >> q;
// cout << n << ' ' << q << endl;
vector<int> a(n);
set<int> s;
for(int i = 0; i < n; i ++) {
cin >> a[i];
if(a[i] == 1) s.insert(i);
}
while(q --) {
int op;
cin >> op;
if(op == 2) {
int i;
cin >> i;
s.erase(i - 1);
cin >> a[i - 1];
if(a[i - 1] == 1) s.insert(i - 1);
}
else {
int sum;
cin >> sum;
int cnt = s.size();
if(sum & 1) {
if(cnt == 0) {
cout << "NO\n";
continue;
}
if(cnt & 1) {
int d = *s.rbegin() - *s.begin() + 1;
int res = 2 * n - cnt;
// cout << res << endl;
if(res >= sum) cout << "YES\n";
else cout << "NO\n";
}
else {
int d1 = 2 * n - 2 * *s.begin() - cnt;
int d2 = 2 * n - 2 * (n - *s.rbegin() - 1) - cnt;
//cout << d1 << ' ' << d2 << endl;
if(sum <= max(d1, d2)) cout << "YES\n";
else cout << "NO\n";
}
}
else {
if(cnt == 0) {
if(2 * n >= sum) cout << "YES\n";
else cout << "NO\n";
continue;
}
if(cnt & 1) {
int d1 = 2 * n - 2 * *s.begin() - cnt;
int d2 = 2 * n - 2 * (n - *s.rbegin() - 1) - cnt;
if(sum <= max(d1, d2)) cout << "YES\n";
else cout << "NO\n";
}
else {
int d = *s.rbegin() - *s.begin() + 1;
int res = 2 * n - cnt;
if(res >= sum) cout << "YES\n";
else cout << "NO\n";
}
}
}
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while(T --) {
solve();
}
}