退役题目集合

2019年07月25日23:56:32

  https://www.hackerrank.com/challenges/sam-and-substrings/editorial

       求一个数字字符串所有子串数字之和,dp[i]表示以第i个字符结尾的总和,列举所有出来可得到递推公式。

2018-05-08 16:56:08

https://csacademy.com/contest/archive/task/swap_pairing/statement/

题目意思是问,给定一个数组,每个数字都精确出现了两次。每一个操作可以交换相邻的两个数字。

要求目标是相同的数字挨在一起,求最小的操作次数。

贪心的做法是最左边的数字肯定不要动,让最右边的数字靠过来。这样最优。然后就是第一次先匹配a[1], 然后再匹配a[2]......这样。

统计的时候用树状数组维护一下就好

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <assert.h>
#include <map>

using namespace std;

const int maxn = 1e5 + 20;

int c[maxn];
int lowbit(int pos) {
    return pos & (-pos);
}

int ask(int pos) {
    int ans = 0;
    while (pos > 0) {
        ans += c[pos];
        pos -= lowbit(pos);
    }
    return ans;
}

void update(int pos, int val) {
    while (pos < maxn) {
        c[pos] += val;
        pos += lowbit(pos);
    }
}

int a[maxn];
bool need[maxn];

map<int, int> mp;

void work() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    for (int i = n; i >= 1; --i) {
        if (mp.count(a[i]) == 0) {
            mp[a[i]] = i;
        } else need[i] = true;
    }
    long long int ans = 0;
    for (int i = 1; i <= n; ++i) {
        if (!need[i]) continue;
        ans += mp[a[i]] - i - 1;
        ans -= ask(mp[a[i]]) - ask(i - 1);
        update(mp[a[i]], 1);
    }
    cout << ans << endl;
}


int main() {
    // freopen("data.txt", "r", stdin);
    work();
    return 0;
}
View Code

A - 一棵简单的线段树

被卡了返回vector<long long int>

又暂时学不会返回引用,惨。。cpp白学

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 2;
const long long int inf = (long long int) 1e18;
const int oo = (int) 1e9;

struct segTree {
    int L, R;
    long long int sum;
    int mx, mi;
} seg[maxn << 2];

int root;

int build(int L, int R) {
    int now = ++root;
    seg[now].sum = 0;
    seg[now].mx = -oo;
    seg[now].mi = oo;
    if (L == R) {
        seg[now].sum = seg[now].mi = seg[now].mx = 0;
        return now;
    }
    int mid = (L + R) >> 1;
    seg[now].L = build(L, mid);
    seg[now].R = build(mid + 1, R);

    seg[now].sum = seg[seg[now].L].sum + seg[seg[now].R].sum;
    seg[now].mx = max(seg[seg[now].L].mx, seg[seg[now].R].mx);
    seg[now].mi = min(seg[seg[now].L].mi, seg[seg[now].R].mi);

    return now;
}

void update(int pos, int val, int L, int R, int cur) {
    if (L == R) {
        seg[cur].mx = seg[cur].mi = seg[cur].sum = val;
        return;
    }
    int mid = (L + R) >> 1;
    if (pos <= mid) {
        update(pos, val, L, mid, seg[cur].L);
    } else update(pos, val, mid + 1, R, seg[cur].R);

    int lson = seg[cur].L, rson = seg[cur].R;

    seg[cur].mx = max(seg[lson].mx, seg[rson].mx);
    seg[cur].mi = min(seg[lson].mi, seg[rson].mi);
    seg[cur].sum = seg[lson].sum + seg[rson].sum;
}

vector<long long int> ask(int be, int en, int L, int R, int cur) {

    // cout << "now" << endl;
    // cout << L << " " << R << endl;
    if (L >= be && R <= en) {
        vector<long long int> vc;
        vc.push_back(seg[cur].sum);
        vc.push_back(seg[cur].mx);
        vc.push_back(seg[cur].mi);
        return vc;
    }
    // cout << L << " " << R << endl;
    int mid = (L + R) >> 1;

    vector<long long int> ans;
    for (int i = 0; i < 3; ++i) ans.push_back(0);
    ans[1] = -inf;
    ans[2] = inf;

    if (be <= mid) {
        vector<long long int> res = ask(be, en, L, mid, seg[cur].L);
        // cout << "left" << " " << L << " " << R << endl;
        // for (int i = 0; i < 3; ++i) {
        //     cout << res[i] << " ";
        // }
        // cout << endl;
        ans[0] += res[0];
        ans[1] = max(ans[1], res[1]);
        ans[2] = min(ans[2], res[2]);
    }
    if (en >= mid + 1) {
        vector<long long int> res = ask(be, en, mid + 1, R, seg[cur].R);
        // cout << "right" << " " << L << " " << R << endl;
        // for (int i = 0; i < 3; ++i) {
        //     cout << res[i] << " ";
        // }
        // cout << endl;
        // cout << "vimi" << " " << L << " " << R << endl;
        // for (int i = 0; i < 3; ++i) {
        //     cout << ans[i] << " ";
        // }
        // cout << endl;
        ans[0] += res[0];
        ans[1] = max(ans[1], res[1]);
        ans[2] = min(ans[2], res[2]);
    }
    return ans;
}

void work() {
    int n;
    scanf("%d", &n);
    build(1, n);
    int q;
    scanf("%d", &q);
    while (q--) {
        int op, one, two;
        scanf("%d%d%d", &op, &one, &two);
        if (op == 0) {
            update(one, two, 1, n, 1);
        } else {
            vector<long long int> vc = ask(one, two, 1, n, 1);
            // cout << "test " << vc[0] << " " << vc[1] << " " << vc[2] << endl;
            printf("%lld
", vc[0] - vc[1] - vc[2]);
        }
    }
}

int main() {
    // freopen("data.txt", "r", stdin);
    work();
    return 0;
}
TLE 5

改了一改就行了

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 2;
const long long int inf = (long long int) 1e18;
const int oo = (int) 1e9;

struct segTree {
    int L, R;
    long long int sum;
    int mx, mi;
} seg[maxn << 3];

int root;

int build(int L, int R) {
    int now = ++root;
    if (L == R) {
        seg[now].sum = seg[now].mi = seg[now].mx = 0;
        return now;
    }
    int mid = (L + R) >> 1;
    seg[now].L = build(L, mid);
    seg[now].R = build(mid + 1, R);

    seg[now].sum = seg[seg[now].L].sum + seg[seg[now].R].sum;
    seg[now].mx = max(seg[seg[now].L].mx, seg[seg[now].R].mx);
    seg[now].mi = min(seg[seg[now].L].mi, seg[seg[now].R].mi);

    return now;
}

void update(int pos, int val, int L, int R, int cur) {
    if (L == R) {
        seg[cur].mx = seg[cur].mi = seg[cur].sum = val;
        return;
    }
    int mid = (L + R) >> 1;
    if (pos <= mid) {
        update(pos, val, L, mid, seg[cur].L);
    } else update(pos, val, mid + 1, R, seg[cur].R);

    int lson = seg[cur].L, rson = seg[cur].R;

    seg[cur].mx = max(seg[lson].mx, seg[rson].mx);
    seg[cur].mi = min(seg[lson].mi, seg[rson].mi);
    seg[cur].sum = seg[lson].sum + seg[rson].sum;
}

void ask(int be, int en, int L, int R, long long int &sum, int &mx, int &mi, int cur) {
    if (L >= be && R <= en) {
        sum += seg[cur].sum;
        mx = max(seg[cur].mx, mx);
        mi = min(seg[cur].mi, mi);
        return;
    }
    int mid = (L + R) >> 1;
    if (be <= mid) {
        ask(be, en, L, mid, sum, mx, mi, seg[cur].L);
    }
    if (en >= mid + 1) {
        ask(be, en, mid + 1, R, sum, mx, mi, seg[cur].R);
    }
}

void work() {
    int n;
    scanf("%d", &n);
    build(1, n);
    int q;
    scanf("%d", &q);
    while (q--) {
        int op, one, two;
        scanf("%d%d%d", &op, &one, &two);
        if (op == 0) {
            update(one, two, 1, n, 1);
        } else {
            long long int sum = 0;
            int mx = -oo;
            int mi = oo;
            ask(one, two, 1, n, sum, mx, mi, 1);
            printf("%lld
", sum - mx - mi);
        }
    }
}

int main() {
    // freopen("data.txt", "r", stdin);
    work();
    return 0;
}
View Code

http://codeforces.com/contest/984/problem/D

画图,然后变成简单的区间DP

#include <bits/stdc++.h>
using namespace std;

const int maxn = 5e3 + 20;
int dp[maxn][maxn];
int f[maxn][maxn];
int a[maxn];

int dfs(int be, int en) {
    if (be > en) {
        assert(false);
    }
    if (be == en) return dp[be][en] = f[be][en] = a[be];
    if (f[be][en] != -1) return f[be][en];
    int left = dfs(be, en - 1);
    int right = dfs(be + 1, en);

    f[be][en] = left ^ right;

    dp[be][en] = max(dp[be + 1][en], max(dp[be][en - 1], left ^ right));
    return f[be][en];
}

void work() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            f[i][j] = dp[i][j] = -1;
        }
    }
    for (int i = 1; i <= n; ++i) {
        scanf("%d", a + i);
    }
    int q;
    scanf("%d", &q);
    while (q--) {
        int L, R;
        scanf("%d%d", &L, &R);
        // cout << L << " " << R << endl;
        dfs(L, R);
        printf("%d
", dp[L][R]);
    }
}

int main() {
    // freopen("data.txt", "r", stdin);
    work();
    return 0;
}
View Code

韩罗塔

#include <cstdio>
#include <cstdlib>
#include <stack>

void move(int val, char from, char broow, char to) {
    printf("%d from %c broow %c to %c
", val, from, broow, to);
}
int step;
void dfs(int n, char a, char b, char c) {
    if (n == 0) return;
    step++;
    if (n == 1) {
        move(n, a, ' ', b);
        return;
    }
    dfs(n - 1, a, c, b);
    move(n, a, ' ', b);
    dfs(n - 1, c, b, a);
}

void work() {
    int n = 5;
    dfs(n, 'A', 'B', 'C');
    printf("%d
", step);
}

int main() {
    work();
    return 0;
}
View Code

光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
你需要设计这样一个函数:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。要求时间复杂度控制在O(N^3*log(M))。
map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
你的路径中应考虑包含重复边的情况。

/*
* @Author: vimiliu
* @Date:   2018-07-18 15:18:42
* @Last Modified by:   vimiliu
* @Last Modified time: 2018-07-18 20:22:43
*/

#include <bits/stdc++.h>
using namespace std;

const int maxn = 200 + 2;

struct Matrix {
    int a[maxn][maxn];
    int col, row;
    void init() {
        for (int i = 1; i <= row; ++i) {
            for (int j = 1; j <= col; ++j) {
                a[i][j] = -1; // can not go
            }
        }
    }
};

void show(struct Matrix a) {
    for (int i = 1; i <= a.row; ++i) {
        for (int j = 1; j <= a.col; ++j) {
            cout << a.a[i][j] << " ";
        }
        cout << endl;
    }
    cout << "debug ------ " << endl;
}

struct Matrix MatrixMul(struct Matrix a, struct Matrix b) {
    struct Matrix res;
    res.row = a.row; //行等于第一个矩阵的行
    res.col = b.col; //列等于第二个矩阵的列
    for (int i = 1; i <= a.row; ++i) {
        for (int j = 1; j <= a.col; ++j) {
            int val = -1; // can not go
            for (int k = 1; k <= b.row; ++k) {
                if (a.a[i][k] == -1 || b.a[k][j] == -1) continue;
                if (val == -1) val = a.a[i][k] + b.a[k][j];
                else val = min(val, a.a[i][k] + b.a[k][j]);
            }
            res.a[i][j] = val;
        } 
    }
    return res;
}

struct Matrix MatrixQuickPow(struct Matrix a, struct Matrix b, int n) {
    while (n > 0) {
        if (n & 1) {
            a = MatrixMul(a, b);
        }
        b = MatrixMul(b, b);
        n >>= 1;
    }
    return a;
}

int e[maxn][maxn];
int n;
void inputData() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            scanf("%d", &e[i][j]);
            if (e[i][j] == 0) e[i][j] = -1;
        }
    }
}

void work() {

    struct Matrix I;
    I.row = I.col = n;
    I.init();
    for (int i = 1; i <= n; ++i) {
        I.a[i][i] = 0;
    }
    struct Matrix b;
    b.row = b.col = n;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            b.a[i][j] = e[i][j];
        }
    }
    // input data
    ///////////////////////////
    int m = 2;
    struct Matrix ans = MatrixQuickPow(I, b, m);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            printf("%d ", ans.a[i][j]);
        }
        printf("
");
    }

}

int main() {
    freopen("data.txt", "r", stdin);
    inputData();
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/9009309.html