codeforces 156 div1

A:给你n个数,求由交替出现的两个数组成的子串的最大长度

      先离散化,dp[i][j]表示当前以i结尾,下一个需要j的最大长度

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <set>

#define pause cout << " press ansy key to continue...",  cin >> chh
#define file_r(x) freopen(x,  "r",  stdin)
#define file_w(x) freopen(x,  "w",  stdout)
#define lowbit(x) ((x) & (-x))
#define repit(i, c) for (__typeof__((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define rep(i, n) for (int i = 0; i < (n); i++)
#define repd(i, n) for (int i = (n - 1); i >= 0; i--)
#define FOR(i, n, m) for (int i = (n); i <= (m); i++)
#define FORD(i, n, m) for (int i = (n); i >= (m); i--)
#define mem(a, x) memset(a, x, sizeof(a))
#define pb push_back
#define X first
#define Y second
#define mp make_pair
#define sqr(r) ((r) * (r))
#define dis(x1, y1, x2, y2) (((x1) - (x2)) * ((x1) - (x2)) + ((y1) - (y2)) * ((y1) - (y2)))

#define debug1(x) cout << #x" = " << x << endl
#define debug2(x, y) cout << #x" = " << x << " " << #y" = " << y << endl
#define debug3(x, y, z) cout << #x" = " << x << " " << #y" = " << y << " " << #z" = " << z << endl
#define debug4(x, y, z, w) cout << #x" = " << x << " " << #y" = " << y << " " << #z" = " << z << " " << #w" = " << w << endl

using namespace std;
int chh;

typedef vector<int> vi;
typedef set<int> si;
typedef map<int, int> mii;
typedef pair<int, int> pii;
typedef long long LL;

const int N = 4005;

int n, e;
int dp[N][N];
int a[N], b[N];

int main() {
    int u, ans;
    while (~scanf("%d", &n)) {
        FOR (i, 1, n) {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        if (n <= 2) {
            printf("%d\n", n);
            continue;
        }
        sort(b + 1, b + n + 1);
        e = unique(b + 1, b + n + 1) - b;
        FOR (i, 1, n) a[i] = lower_bound(b + 1, b + e, a[i]) - b;
        memset(dp, -1, sizeof(dp));
        dp[a[1]][e + 1] = 1;
        FOR (i, 2, n) {
            u = a[i];
            FOR (j, 1, e) {
                if (dp[j][u] != -1) dp[u][j] = max(dp[u][j], dp[j][u] + 1);
                if (dp[j][e + 1] != -1) {
                    dp[u][j] = max(dp[u][j], 2);
                }
            }
            dp[u][e + 1] = 1;
        }
        ans = 2;
        FOR (i, 1, e) FOR (j, 1, e) ans = max(ans, dp[i][j]);
        printf("%d\n", ans);
    }
    return 0;
}


B:在n * n的地图中给你一个点,每次可以向四个方向扩展,问最少扩展多少次后,

      遍历的点大于等于c

      二分枚举答案

int n, x, y, c;

LL doIt(int l, int u, int s, int x, int y) {
    int h = max(u, x - (s - y + l));
    LL ans = (LL)(x - h + 1) * (y - l + 1);
    if (h - 1 >= u) ans += (LL)(u + 2 * y - 2 * l - h + 1) * (h - u) / 2;
    return ans;
}

LL cal(int s) {
    int h;
    int l = max(1, y - s), r = min(n, y + s);
    int u = max(1, x - s), d = min(n, x + s);
    LL ans = 0;
    ans += doIt(l, u, s, x, y);
    ans += doIt(y - (r - y), u, s, x, y);
    ans += doIt(l, x - (d - x), s, x, y);
    ans += doIt(y - (r - y), x - (d - x), s, x, y);
    ans -= r - l + 1 + d - u + 1 + 1;
    return ans;
}

int main() {
    int s, t, mid;
    LL tol;
    while (~scanf("%d %d %d %d", &n, &x, &y, &c)) {
        if (c == 1) {
            puts("0");
            continue;
        }
        s = 1, t = 1000000000;
        while (s != t) {
            mid = (s + t) >> 1;
            tol = cal(mid);
            if (tol >= c) t = mid;
            else s = mid + 1;
        }
        printf("%d\n", s);
    }
    return 0;
}





      


你可能感兴趣的:(codeforces 156 div1)