昨晚写的时候序号2的6分点没过
今天终于去了趟市里,从小到大第一次,真不容易。。。回来坐车上看着窗外,想了想这题,瞬间想到了。。。
说说我的思路:(以题目中例子为例)
因为第二行给定颜色序列你肯定要分清先后关系,这里我就用1~m(m是给定的颜色个数)与给定的2、3、1、5、6一一映射 ,
2、3、1、5、6映射 1、2、3、4、5再由1、2、3、4、5映射回2、3、1、5、6;
当然估计有其他好的办法,我反正怎么看都觉得繁,没准可以写一个找前驱的函数,应该也很简单,或者比如a[6] = 5, a[5] = 1, a[1] = 3。。。
因为题目中给了n,数组范围确定
可设置三个数组:
1、喜欢的颜色序号 找到 喜欢的颜色的顺序,a[2] = 1, a[3] = 2, a[1] = 3。。。
2、喜欢的颜色的顺序 找到 喜欢的颜色序号,b[1] = 2, b[2] = 3, b[3] = 1。。。
3、暂存喜欢的颜色序号在长度L的色谱?上的符合题目要求的最大字串长:
比如例子:2 2 4 1 5 5 6 3 1 1 5 6
1 2 3 4 5 6 3 4 5 6 7
第1个扫描到2,则count[2] = 1
第2个扫描到2,则count[2] = count[2] + 1 = 2
第3个跳过
第4个扫描到1,则count[1] = count[2] + 1 = 3
第5个扫描到5,则count[5] = count[1] + 1 = 4
第6个扫描到5,则count[5] = count[5] + 1 = 5
。。
。。
昨天是这样想的,每次都找到第一个等于小于当前颜色顺序且count值不为0的序号,然后操作count[当前序号] = count[找到的序号] + 1;
结果有一个点没过,其实就是这种情况:
L的序列为 2 2 5 2 2 5
按照原先的想法就是 1 2 3 3 4 4
其实应该 1 2 3 3 4 5
重点在于每次应该找到序号顺序小于等于当前序号的顺序,并且count值最大的那个序号,令count[当前序号] = count[找到count值最大的序号] + 1;
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<string>
#include<set>
using namespace std;
int main(){
int n, m, l;
cin>>n>>m;
int a[n + 1] = {0};
int b[n + 1] = {0};
int count[n + 1] = {0};//统计个数
for(int i = 1; i <= m; i++){
int temp;
scanf("%d",&temp);
a[temp] = i;//前后顺序用1~n
b[i] = temp;
}
cin>>l;
int sum[l] = {0};
int maxl = 0;
for(int i = 0; i < l; i++){
int temp;
scanf("%d",&temp);
if(a[temp] == 0) continue;
int k = a[temp];
int maxk = 0;
int tempmax = 0;
while(k > 0){
if(tempmax < count[b[k]]){
tempmax = count[b[k]];
maxk = k;
}
k--;
}
if(maxk == 0) maxk++;
count[b[a[temp]]] = count[b[maxk]] + 1;//count[temp] = count[b[maxk]] + 1;等价
sum[i] = count[b[a[temp]]];//sum[]可不写,写的话直观一点
if(maxl < sum[i]) maxl = sum[i];
}
cout<<maxl;
return 0;
}