https://vjudge.net/problem/UVA-11456
题意
艾琳是个开火车的机师,她也负责车厢的调度。她喜欢把车厢依重量由大到小排列,把最重的车厢摆在火车的前方。
不幸的是,排列车厢并不容易。你不能直接把一截车厢拿起来放在别处。把一截车箱插入现有的列车中间并不切实际。一截车厢仅能接在列车的前面或后面。
车厢以事先排定的顺序抵达车站。当一截车厢抵达时,艾琳可以把它接在列车的前方或后方,或根本不要这截车厢。列车越长越好,但是其中的车厢要依重量排列。
依车厢抵达的顺序给你车厢的重量,艾琳所能接出的最长火车是多长?
思路: 比如 7 9 5 6 4 8 这个例子,平凡的做法是先取一个数字,比如5,那么在5出现前先找大于5最长上升子序列,在5出现后,再找到小于5的下降子序列,并且那个上升子序列继续上升。或者在5出现前是小于5的下降子序列,5出现后再找大于5的上升,刚才那个下降的序列继续下降。因此,我们先按照出现顺序标记,然后按照重量排序,可以使用STL中的map,然后以5为分界,那么前面的都小于5,后面的都大于5. 前面从头到尾计算下降,后面从未到前计算下降。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;
#define MAX 2005
int main() {
int n,t;
map<int,int> imap;
cin>>t;
vector<int> uplist,downlist,sq;
map<int,int>::iterator it;
while(t--) {
cin>>n;
int tn=0;
int w;
imap.clear();
while(tn<n) {
cin>>w;
imap.insert(make_pair(w,++tn));
}
//second的最大下降子序列
uplist.resize(n);
sq.clear();
it=imap.begin();
for(it; it!=imap.end(); it++) {
sq.push_back(it->second);
}
for(int i=0; i<n; i++) {
uplist[i]=1;
for(int j=0; j<i; j++)
if(sq[i]<sq[j]) {
uplist[i]=max(uplist[j]+1,uplist[i]);
//break;
}
}
//second的最大下降子序列 逆方向
downlist.resize(n);
for(int i=n-1; i>-1; i--) {
downlist[i]=1;
for(int j=n-1; j>i; j--)
if(sq[i]<sq[j]) {
downlist[i]=max(downlist[j]+1,downlist[i]);
//break;
}
}
int imax=0;
for(int i=0; i<n; i++) {
imax=max(imax,uplist[i]+downlist[i]-1);
}
cout<<imax<<endl;
}
return 0;
}