题目大意:给定一个数组a,他们每个元素具有red和blue中的其中一种,red属性的元素可以变成大于等于这个元素的任意数,blue属性的元素可以变成小于等于这个元素的任意数。现有一个数组a,问他们能否组成一个新数列包含1到n的所有数。
解题思路:
第一种:
创建一个桶数组,存入每个数的个数。对每个a元素进行判断,如果属性是blue,就从[ 1,a[i] ]中寻找空桶并放入,a[i]桶中的个数减一;如果属性是red,就从[ a[i],n ] 中寻找空桶并放入,a[i]桶中的个数减一。最后判断所有桶中的个数是否都为1。
第一种思路的问题在于a[i]的取值范围在[ -1e9,1e9 ] 之间,这样的数组开不出来,如果还要往这个思路继续发展,可以考虑用哈希表拉链法。
第二种:
讲属性为blue和red的元素分别push到两个数组里,因为具有blue属性的元素可以转变为比该元素值小的任意数,所以sort( < ) blue数组里的元素之后,排序后每个位置的元素如果出现比这个位置的序号 + 1小的元素,则这个问题是不能解决的,输出no;同样的道理,sort( > ) red 的数组里的元素值应该都小于n - 序号。
即:
1 bool f = 1; 2 sort(blue.begin(),blue.end()); 3 for(int i = 0;i < blue.size();i ++){ 4 if(blue[i] < i + 1)f = 0; 5 } 6 sort(red.begin(),red.end()); 7 reverse(red.begin(),red.end()); 8 for(int i = 0;i < red.size();i ++){ 9 if(red[i] > n - i)f = 0; 10 }
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define MP make_pair 5 #define SZ(X) ((int)(X).size()) 6 typedef pair<int, int> PII; 7 const int INF = 0x3f3f3f3f; 8 const int N = 1e6 + 10; 9 int T[N],l,r; 10 11 int main(){ 12 int _; 13 scanf("%d",&_); 14 while(_--){ 15 int n; 16 scanf("%d",&n); 17 18 for(int i = 0;i < n;i ++){ 19 scanf("%d",&T[i]); 20 } 21 22 string s; 23 vector<int>blue,red; 24 25 cin >> s; 26 27 for(int i = 0;i < n;i ++){ 28 if(s[i] == 'B'){ 29 blue.push_back(T[i]); 30 } 31 else { 32 red.push_back(T[i]); 33 } 34 35 } 36 37 bool f = 1; 38 sort(blue.begin(),blue.end()); 39 for(int i = 0;i < blue.size();i ++){ 40 if(blue[i] < i + 1)f = 0; 41 } 42 sort(red.begin(),red.end()); 43 reverse(red.begin(),red.end()); 44 for(int i = 0;i < red.size();i ++){ 45 if(red[i] > n - i)f = 0; 46 } 47 48 printf(f?"YES\n":"NO\n"); 49 blue.clear(); 50 red.clear(); 51 } 52 53 return 0; 54 }