题意:
告诉你n和k的值,然后给你n个数,允许你进行一种操作:
选择一个区间[l,r],然后将区间里的数全部变成区间的中位数
(如果区间长度为偶数,则选择中间两个数里面小的那个)
操作可以进行无限次,问你能不能把这个数组全部变成k
思路:
刚开始的思路是找一个区间,把这个区间的数全部变成k,每次将区间长度扩大1,就能多生成一个k,直到全部变成k,
然后我又想,将数组中的数标记,大于k的标记为1,小于k的标记为-1,等于k的标记为0。问题就转化成了找一个区间,区间和为0,且区间中包含k。
对于区间和为0这个问题,可以求个区间值的前缀和,s[r]-s[l-1]=0,满足条件,所以s[r] == s[l-1],所以每次算前缀和的时候看这个值之前有没有出现过就行了,
对于区间包含k的问题,用ss[i]表示前i个数出现几个k,[l,r]包含k即ss[r]-ss[l-1]>0,
如此判断就行了
结果wa了。
其实这个思路第一步就错了,看这组数据
输入:
9 7
7 6 4 5 3 2 1 8 9
输出:
yes
不需要直接找一个区间,把这个区间的数全部变成k,可以先生成某个区间,然后和另一个区间合并,然后再变成k。
也就是只要k左右有大于等于k的值,就可以一直扩大,那么只需要找到两个或三个大于等于k的值,一直扩大,然后遇到k,然后再扩大就可以了,
ac代码
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <string>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <stack>
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define uint unsigned int
using namespace std;
int n, k, t, a[100009];
int main() {
cin >> t;
while (t--) {
cin >> n >> k;
bool ok = (n == 1);
bool present = false;
for (int i = 0; i < n; i++) {
cin >> a[i];
ok = ok || (a[i] >= k && ((i >= 1 && a[i - 1] >= k) || (i >= 2 && a[i - 2] >= k)));
present = present || (a[i] == k);
}
if (ok && present)
cout << "yes\n";
else
cout << "no\n";
}
return 0;
}

4973

被折叠的 条评论
为什么被折叠?



