2020-02-18

搭积木

小明有一袋子长方形的积木,如果一个积木A的长和宽都不大于另外一个积木B的长和宽,则积木A可以搭在积木B的上面。好奇的小明特别想知道这一袋子积木最多可以搭多少层,你能帮他想想办法吗?定义每一个长方形的长L和宽W都为正整数,并且1 <= W <= L <= INT_MAX, 袋子里面长方形的个数为N, 并且 1 <= N <= 1000000.假如袋子里共有5个积木分别为 (2, 2), (2, 4), (3, 3), (2, 5), (4, 5), 则不难判断这些积木最多可以搭成4层, 因为(2, 2) < (2, 4) < (2, 5) < (4, 5)。

#include 
#include 
using namespace std;
#define max_n 1000000

struct Data {
    int x, y;
} arr[max_n + 5];
int val[max_n + 5];
int len[max_n + 5], ans;

bool cmp(const Data &a, const Data &b) {
    if (a.x - b.x) return a.x < b.x;
    return a.y < b.y;
}

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> arr[i].x >> arr[i].y;
    }
    sort(arr, arr + n, cmp);
    for (int i = 0; i < n; i++) {
        val[i] = arr[i].y;
    }
    len[0] = -1;
    ans = 0;
    for (int i = 0; i < n; i++) {
        int pos = upper_bound(len, len + ans + 1, val[i]) - len;
        ans = max(ans, pos);
        len[pos] = val[i];
    }
    cout << ans << endl;
    return 0;
}

魔法深渊

题目描述
前几个月放映的头号玩家简直火得不能再火了,作为一个探索终极AI的研究人员,月神自然去看了此神剧。由于太过兴奋,晚上月神做了一个奇怪的梦,月神梦见自己掉入了一个被施放了魔法的深渊,月神想要爬上此深渊。已知深渊有N层台阶构成(1 <= N <= 1000),并且每次月神仅可往上爬2的整数次幂个台阶(1、2、4、....),请你编程告诉月神,月神有多少种方法爬出深渊.

#include 
using namespace std;
#define max_n 1000
#define mod_num (1000000000LL + 3)
long long f[max_n + 5];

void init() {
    f[0] = 1;
    for (int i = 1; i <= max_n; i++) {
        for (int j = 1; j <= i; j <<= 1) {
            f[i] += f[i - j];
            f[i] %= mod_num;
        }
    }
    return ;
}

int main() {
    init();
    int m, n;
    cin >> m;
    while (m--) {
        cin >> n;
        cout << f[n] << endl;
    }
    return 0;
}

善变的同伴

题目描述
又到了吃午饭的时间,你和你的同伴刚刚研发出了最新的GSS-483型自动打饭机器人,现在你们正在对机器人进行功能测试。
为了简化问题,我们假设午饭一共有N个菜,对于第i个菜,你和你的同伴对其定义了一个好吃程度(或难吃程度,如果是负数的话……)A[i],
由于一些技(经)术(费)限制,机器人一次只能接受一个指令:两个数L, R——表示机器人将会去打第L~R一共R-L+1个菜。
本着不浪费的原则,你们决定机器人打上来的菜,含着泪也要都吃完,于是你们希望机器人打的菜的好吃程度之和最大
然而,你善变的同伴希望对机器人进行多次测试(实际上可能是为了多吃到好吃的菜),他想知道机器人打M次菜能达到的最大的好吃程度之和
当然,打过一次的菜是不能再打的,而且你也可以对机器人输入-1, -1,表示一个菜也不打

#include 
using namespace std;
#define max_n 100000
struct Node { 
    int val, flag;
    int l, r;
} l[max_n + 5];
int n, m, head;

void del(int p) {
    if (p == 0) return ;
    l[p].flag = 1;
    l[l[p].l].r = l[p].r;
    l[l[p].r].l = l[p].l;
    l[p].l = l[p].r = 0;
    return ;
}

typedef pair PII;

inline int sign(int x) {
    if (x < 0) return -1;
    if (x > 0) return 1;
    return 0;
}

int main() {
    cin >> n >> m;
    l[0].r = 1, l[0].l = 0;
    for (int i = 1; i <= n; i++) {
        cin >> l[i].val;
        l[i].l = i - 1;
        l[i].r = (i + 1) * (i < n);
    }
    set s;
    int p = l[0].r, cnt = 0, sum = 0;
    while (p) {
        while (l[p].r && sign(l[p].val) * sign(l[l[p].r].val) >= 0) {
            l[p].val += l[l[p].r].val;
            del(l[p].r);
        }
        s.insert(PII(abs(l[p].val), p));
        if (l[p].val > 0) cnt += 1, sum += l[p].val;
        p = l[p].r;
    }
    while (cnt > m) {
        int ind = s.begin()->second;
        s.erase(s.begin());
        if (l[ind].flag) continue;
        if ((l[ind].r && l[ind].l) || l[ind].val > 0) {
            sum -= abs(l[ind].val);
            cnt -= 1;
            l[ind].val += l[l[ind].l].val;
            l[ind].val += l[l[ind].r].val;
            del(l[ind].l); del(l[ind].r);
            s.insert(PII(abs(l[ind].val), ind));
        } else {
            del(ind);
        }
    }
    cout << sum << endl;
    return 0;
}

合并数组

题目描述
请实现一个函数,功能为合并两个升序数组为一个升序数组

using namespace std;

int arr[3][100000];

int read_line_to(int k, int &n) {
    int a;
    n = 0;
    while (~scanf("%d", &a)) {
        arr[k][n++] = a;
        if (getchar() == '\n') break;
    }
    return n;
}

int solve() {
    int n, m;
    if (!read_line_to(0, n)) return 0;
    read_line_to(1, m);
    int p1 = 0, p2 = 0, t = 0;
    while (p1 < n || p2 < m) {
        if (p2 == m || (p1 < n && arr[0][p1] < arr[1][p2])) {
            arr[2][t++] = arr[0][p1++];
        } else {
            arr[2][t++] = arr[1][p2++];
        }
    }
    for (int i = 0; i < t; i++){
        i && cout << ",";
        cout << arr[2][i];
    }
    cout << endl;
    return t;
}

int main() {
    int a, k = 0;
    while (solve()) ;
    return 0;
}

游戏海报

小明有26种游戏海报,用小写字母"a"到"z"表示。小明会把游戏海报装订成册(可能有重复的海报),册子可以用一个字符串来表示,每个字符就表示对应的海报,例如abcdea。小明现在想做一些“特别版”,然后卖掉。特别版就是会从所有海报(26种)中随机选一张,加入到册子的任意一个位置。
那现在小明手里已经有一种海报册子,再插入一张新的海报后,他一共可以组成多少不同的海报册子呢?


#include 
using namespace std;

char str[25];
int p[25], n, ans = 0;

int count_one(int x) {
    int cnt = 0;
    while (x) {
        cnt += 1;
        x &= (x - 1);
    }
    return cnt;
}

int main() {
    str[0] = 1;
    cin >> str;
    n = strlen(str);
    for (int i = 0; i <= n; i++) p[i] = (1 << 26) - 1;
    for (int i = 0; str[i]; i++) {
        ans += count_one(p[i]);
        if ((p[i] & (1 << (str[i] - 'a'))) == 0) continue;
        int mask = ((1 << 26) - 1) ^ (1 << (str[i] - 'a'));
        for (int j = i; str[j] == str[i]; j++) {
            p[j + 1] &= mask;
        }
    }
    ans += count_one(p[n]);
    cout << ans << endl;
    return 0;
}

latex爱好者

latex自然是广大研究人员最喜欢使用的科研论文排版工具之一。月神想在iPhone 上查阅写好的paper,但是无赖iPhone 上没有月神喜欢使用的阅读软件,于是月神也希望像tex老爷爷Donald Knuth那样自己动手do it yourself一个。在DIY这个阅读软件的过程中,月神碰到一个问题,已知iPhone屏幕的高为H,宽为W,若字体大小为S(假设为方形),则一行可放W / S(取整数部分)个文字,一屏最多可放H / S (取整数部分)行文字。已知一篇paper有N个段落,每个段落的文字数目由a1, a2, a3,...., an表示,月神希望排版的页数不多于P页(一屏显示一页),那么月神最多可使用多大的字体呢?

#include 
using namespace std;
const int max_n = 100000;

int val[max_n + 5];
int n, p, h, w;

bool check(int mid) {
    int cnt = w / mid, sum = 0;
    for (int i = 0; i < n; i++) {
        sum += val[i] / cnt + (val[i] % cnt != 0);
    }
    return sum <= (h / mid) * p;
}

int bs(int l, int r) {
    if (l == r) return l;
    int mid = (l + r + 1) >> 1;
    if (check(mid)) return bs(mid, r);
    return bs(l, mid - 1);
}

int main() {
    while (cin >> n >> p >> h >> w) {
        for (int i = 0; i < n; i++) cin >> val[i];
        cout << bs(1, w) << " ";
    }
    return 0;
}

回文字符串

最大回文子串是被研究得比较多的一个经典问题。最近月神想到了一个变种,对于一个字符串,如果不要求子串连续,那么一个字符串的最大回文子串的最大长度是多少呢。

#include 
#include 
#include 
using namespace std;

string str1, str2;
int f[1005][1005] = {0};

int main() {
    cin >> str1;
    str2 = str1;
    reverse(str1.begin(), str1.end());
    for (int i = 1; i <= str1.size(); i++) {
        for (int j = 1; j <= str2.size(); j++) {
            f[i][j] = max(f[i - 1][j], f[i][j - 1]);
            if (str1[i - 1] == str2[j - 1]) {
                f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
            }
        }
    }
    cout << f[str1.size()][str1.size()] << endl;
    return 0;
}

你可能感兴趣的:(2020-02-18)