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; }