C.学习了一下STL List的insert的用法,然后这道题直接用List模拟即可。函数原型:iterator insert(iterator where, value_type val);注意这里的插入是在当前指针位置上赋值,然后把原来这个位置上的值后移。例如1,2,3 指针it = 2,则insert(it,5)后为,1,5,2,3 且it自动加1,即it等于3,所以要想it指回原来的位置,必须把it--。
string s;
list<int> L;
list<int>::iterator it;
int main(){
while(cin >> s){
L.clear();
L.push_back(1);
it = L.begin();
int len = s.length();
for(int i = 0;i < len-1;i++){
if(s[i] == 'l'){
L.insert(it,i+2);
--it;
}
else{
L.insert(++it,i+2);
--it;
}
}
for(it = L.begin();it != L.end();it++) cout << *it << endl;
}
return 0;
}
D.dp。类似求最长上升子序列的nlogn算法,必须维护一个前面dp值中符合要求的最大值。这个题目是要求两个数不能互质,即它们之间存在公约数。这样我们就需要先求出每个数的质因数有哪些,这个问题用筛法稍加变形即可解决,筛每个质数的倍数时,把那些倍数的公约数里都push_back这个质数。然后再维护一个Max[]数组,Max[i]记录的是dp的序列中,末位的数存在i这个约数的最大的那个dp值,dp[i] = 1 + max(i所有约数的Max)。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 5;
int num[maxn];
int prime[maxn];
int dp[maxn];
int Max[maxn];
vector<int> pri[maxn];
void make_prime(){
memset(prime,0,sizeof(prime));
for(int i = 0;i < maxn;i++)
pri[i].clear();
for(int i = 2;i < maxn;i++){
if(!prime[i]){
for(int j = i;j < maxn;j+=i){
pri[j].push_back(i);
prime[j] = 1;
}
}
}
}
int main(){
int n;
make_prime();
while(cin >> n){
for(int i = 0;i < n;i++) cin >> num[i];
sort(num,num+n);
memset(Max,0,sizeof(Max));
int ans = 0;
for(int i = 0;i < n;i++){
int temmax = 0;
for(int j = 0;j < pri[num[i]].size();j++){
temmax = max(temmax,Max[pri[num[i]][j]]);
}
dp[i] = temmax + 1;
for(int j = 0;j < pri[num[i]].size();j++){
Max[pri[num[i]][j]] = max(dp[i],Max[pri[num[i]][j]]);
}
ans = max(ans,dp[i]);
}
cout << ans << endl;
}
return 0;
}
E.
dp[i]表示第i种颜色结尾的最大值。
这样对于所给的ball,从前往后扫,那么dp[i]就有四种转移方向;
1 不要当前这个ball, dp[i] 不变
2 以当前位置为起点, dp[i] = v[i]*b
3 和前面颜色相同, dp[i]+v[i]*a
4 和前面颜色不同, 不同颜色中dp最大的那个Maxother+v[i]*b
这样剩下的问题就是求Maxother了,直接扫一遍所有的dp[i]肯定超时,
按照以往的经验,我们肯定需要维护一个额外的信息,来做到O(1)的算法,
因为O(nq)已经是10^7了。假如我们记录下所有dp的最大值,则如果当前颜色和那个最大值的颜色相同,我们就必须重新找一遍不是那个颜色的最大值,其实就是第二大值
这样题目就解出来了,只需要维护最大值和次大值,以及他们的颜色就可以了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
using namespace std;
typedef long long LL;
const int maxn = 100000 + 5;
const LL INF = 1e18;
LL v[maxn],c[maxn];
LL dp[maxn];
int main(){
int n,q;
LL Max1,Max2,ans;
int pos1,pos2;
while(cin >> n >> q){
for(int i = 0;i < n;i++) cin >> v[i];
for(int i = 0;i < n;i++) cin >> c[i];
while(q--){
LL a,b;
cin >> a >> b;
for(int i = 1;i <= n;i++) dp[i] = -INF;
ans = 0;
Max1 = Max2 = -INF;
pos1 = pos2 = 0;
for(int i = 0;i < n;i++){
LL Maxother;
if(c[i] == pos1) Maxother = Max2;
else Maxother = Max1;
dp[c[i]] = max(dp[c[i]],max(dp[c[i]]+v[i]*a,Maxother+v[i]*b));
dp[c[i]] = max(dp[c[i]],v[i]*b);
ans = max(ans,dp[c[i]]);
if(dp[c[i]] >= Max1){
if(c[i] != pos1){
Max2 = Max1; pos2 = pos1;
Max1 = dp[c[i]]; pos1 = c[i];
}
else{
Max1 = dp[c[i]];
}
}
else if(dp[c[i]] > Max2){
Max2 = dp[c[i]];
pos2 = c[i];
}
}
cout << ans << endl;
}
}
return 0;
}