[AH2017 / HNOI2017] big brother (DP + Search + two-pointers)

Face questions

LOJ Portal

answer

There are many operations per day, but in fact can be divided into two categories.

The first class only with their self-confidence about the values: Brush title water / Gangster being ridiculed.

The second type of big brother confidence value related to: L + = 1, F is equal by L, Haizui, hate big brother

So for the first category, we hate as long as the big brother before he died confident non-negative value on the line. To ensure that the confidence values ​​may be non-negative by DP find out how many days remain up to a second type of operation.

Hypothesis out up to leave \ (D \) days to carry out his things, the problem is converted into a total of only \ (D \) day, every day can be L + = 1, F take equal L, Huanzui, hate big brother.

Then by violence \ (BFS \) obtained spent \ (d \) days can hate out heavyweights \ (f \) point confidence value \ ((d, f) \ ) number right, the need to reduce the search time sticks ( \ (F \) exceed the maximum \ (C_i \) is not continued).

After seeking out press \ (F \) as a first key, \ (D \) as the second sort key.

Since a maximum of two can hate, hate or not hate Obviously once. Hate twice asked is whether the presence of \ ((d1, f1), (d2, f2) \) satisfies \ (f1 + f2 \ le C \) and \ (f1 + f2 + (D -d1-d2) \ ge C \) .

We enumerate back to front \ (i \) , set pointer \ (j \) satisfies \ (f_i + f_j \ le C \) and the maximum. Then fixed \ (I \) , then, \ (F1, D, D1, C \) is the predetermined value, then just requires \ (f2-d2 \) is the maximum value on the line. Direct deposit on the line. For obvious monotonic, \ (J \) position must be incremental. So direct deposit with a variable \ (j \) on the line.

CODE

#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long LL;
const int MAXN = 105;
const int MAXM = 25;
int n, m, mc, D, a[MAXN], w[MAXN], C[MAXM], mxc;
int f[MAXN][MAXN];
int predp() {
    f[0][mc] = 0;
    for(int i = 1; i <= n; ++i)
        for(int j = a[i]; j <= mc; ++j) {
            f[i][j-a[i]] = max(f[i][j-a[i]], f[i-1][j]+1);
            f[i][min(j-a[i]+w[i],mc)] = max(f[i][min(j-a[i]+w[i],mc)], f[i-1][j]);
        }
    int re = 0;
    for(int i = 1; i <= n; ++i) //注意这里不能只求f[n][i](i=1...mc)的最大值,因为可以没到第n天就把大佬怼死了
        for(int j = 0; j <= mc; ++j)
            re = max(re, f[i][j]);
    return re;
}
struct node {
    int x; pii y;
};
queue<node>myq;
map<pii, bool>vis;
pii val[2000005];
int cnt;
void BFS() {
    myq.push((node){ 1, pii(1, 0) });
    while(!myq.empty()) {
        int d = myq.front().x, F = myq.front().y.first, L = myq.front().y.second; myq.pop();
        if(d >= D) break;
        myq.push((node){ d+1, pii(F, L+1) });
        if(L > 1 && 1ll*F*L <= mxc && !vis.count(pii(F*L, d+1))) {
        //这里判重我写的map 结果loj过了 luogu上过不了,必须手写hash表才能过
            myq.push((node){ d+1, pii(F*L, L) });
            vis[pii(F*L, d+1)] = 1;
            val[++cnt] = pii(F*L, d+1);
        }
    }
}
int main () {
    scanf("%d%d%d", &n, &m, &mc);
    for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);
    for(int i = 1; i <= m; ++i) scanf("%d", &C[i]), mxc = max(mxc, C[i]);
    D = predp(); BFS(); sort(val + 1, val + cnt + 1);
    for(int i = 1; i <= m; ++i) {
        if(C[i] <= D) { puts("1"); continue; } //不怼
        bool flg = 0; int mx = -0x3f3f3f3f;
        for(int j = cnt, k = 1; j >= 1; --j) { //固定j 移动k
            while(k <= cnt && val[k].first + val[j].first <= C[i]) {
                mx = max(mx, val[k].first-val[k].second);
                ++k;
            }
            if(val[j].first-val[j].second+D+mx >= C[i]) { flg = 1; break; } //怼两次
            if(val[j].first <= C[i] && val[j].first+D-val[j].second >= C[i]) { flg = 1; break; } //怼一次
        }
        printf("%d\n", flg);
    }
}

Guess you like

Origin www.cnblogs.com/Orz-IE/p/12093716.html