Codeforces 940 区间DP单调队列优化

A

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-8;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxm = 300;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll mod = 3e7;
int num[105];
int main()
{
    int n, d;
    cin >> n >> d;
    int anser = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> num[i];
    }
    if (n == 1)
    {
        cout << 0 << endl;
        return 0;
    }
    sort(num + 1, num + 1 + n);
    int now = num[n] - num[1];
    int l = 1;
    int r = n;
    for (int i = n - 1; i >= 1; i--)
    {
        for (int j = 1; j <= n - i; j++)
        {
            if (num[j + i] - num[j] <= d)
            {
                cout << n - i - 1 << endl;
                return 0;
            }
        }
    }
    cout<<n-1<<endl;
    return 0;
}
View Code

B

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-8;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxm = 300;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll mod = 3e7;
int num[105];
int main()
{
        ll n, k, a, b;
        cin >> n >> k >> a >> b;
        ll now = n;
        ll cost = 0;
        ll remain, aim;
        if (k == 1)
        {
                cost += 1LL * a * (now - 1);
                cout << cost << endl;
                return 0;
        }
        while (now != 1)
        {
                if (now < k)
                {
                        cost += 1LL * a * (now - 1);
                        break;
                }
                remain = now % k;
                cost += remain * a;
                now -= remain;
                aim = now / k;
                cost += min(1LL * a * (now - aim), 1LL * b);
                now = aim;
        }
        cout << cost << endl;
        return 0;
}
View Code

C

找字典序最小的比给定字符串S大的字符串T

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-8;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxm = 300;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll mod = 3e7;
int num[30];
int nextt[30];
int main()
{
        int n, k;
        string a;
        cin >> n >> k >> a;
        for (int i = 0; i < n; i++)
        {
                num[a[i] - 'a'] = 1;
        }
        for (int i = 0; i <= 25; i++)
        {
                for (int j = i + 1; j <= 25; j++)
                {
                        if (num[j])
                        {
                                nextt[i] = j;
                                break;
                        }
                }
        }
        if (k > n)
        {
                cout << a;
                int aim;
                for (int i = 0; i <= 25; i++)
                {
                        if (num[i])
                        {
                                aim = i;
                                break;
                        }
                }
                char ch = 'a' + aim;
                for (int i = 1; i <= k - n; i++)
                {
                        cout << ch;
                }
                cout << endl;
        }
        else
        {
                int aim;
                int cur;
                for (int i = k - 1; i >= 0; i--)
                {
                        if (nextt[a[i] - 'a'] != 0)
                        {
                                aim = nextt[a[i] - 'a'];
                                cur = i;
                                break;
                        }
                }
                for (int i = 0; i < cur; i++)
                {
                        cout << a[i];
                }
                char ch = aim + 'a';
                cout << ch;
                for (int i = 0; i <= 25; i++)
                {
                        if (num[i])
                        {
                                aim = i;
                                break;
                        }
                }
                ch = aim + 'a';
                for (int i = 1; i <= k - cur - 1; i++)
                {
                        cout << ch;
                }
                cout << endl;
        }
        return 0;
}
View Code

D

在01边界的时候更新答案范围即可

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-8;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxm = 300;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll mod = 3e7;
int num[100005];
int minnum[100005];
int maxnum[100005];
int main()
{
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
                scanf("%d", &num[i]);
        }
        string a;
        cin >> a;
        for (int i = 5; i <= n; i++)
        {
                int maxn = -1000000001;
                for (int j = 0; j <= 4; j++)
                {
                        maxn = max(maxn, num[i - j]);
                }
                maxnum[i] = maxn;
        }
        for (int i = 5; i <= n; i++)
        {
                int minn = 1000000001;
                for (int j = 0; j <= 4; j++)
                {
                        minn = min(minn, num[i - j]);
                }
                minnum[i] = minn;
        }
        int l = -1000000000;
        int r = 1000000000;
        for (int i = 4; i <= n - 1; i++)
        {
                if (a[i] == '1' && a[i - 1] == '0')
                {
                        l = max(l, maxnum[i + 1] + 1);
                }
                if (a[i] == '0' && a[i - 1] == '1')
                {
                        r = min(r, minnum[i + 1] - 1);
                }
        }
        cout << l << " " << r << endl;
        return 0;
}
View Code

E

单调队列优化DP

可以证明全局最小值<=局部最小值 所以全部块要不是一块一块的 要不就是C块里面的

因为每一个块有两种选择 所以DP方程为dp[i]=min(dp[i-1]+num[i],dp[i-c]+pre[i]-pre[i-c]-min(num[j]) ) [i-c+1<=j<=i]

dp[i]为到第i位最少需要的代价

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!\n")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
const int MAXN = 1e5 + 5;
ll num[MAXN];
int q[MAXN];
int head, tail;
ll dp[MAXN];
ll pre[MAXN];
list<int> que;
int main()
{
        int n, c;
        cin >> n >> c;
        for (int i = 1; i <= n; i++)
        {
                scanf("%lld", num + i);
                pre[i] = pre[i - 1] + num[i];
        }
        for (int i = 1; i <= n; i++)
        {
                dp[i] = dp[i - 1] + num[i];
                while (head >= tail && i - c >= q[tail])
                {
                        tail++;
                }
                while (head >= tail && num[q[head]] > num[i])
                {
                        head--;
                }
                q[++head] = i;
                if (i >= c)
                {
                        dp[i] = min(dp[i], dp[i - c] + pre[i] - pre[i - c] - num[q[tail]]);
                }
        }
        cout << dp[n] << endl;
}
View Code

 

posted @ 2018-03-20 21:27  Aragaki  阅读(279)  评论(0编辑  收藏  举报