CF 162(div2)

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


 

你可能感兴趣的:(CF 162(div2))