ARC081

Make a Rectangle

要么取同一种数,要么取最大和次大

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    scanf("%d", &n);
    map<int,int> f;
    vector<int> a(n);
    for (int i=0; i<n; ++i) {
        scanf("%d", &a[i]);
        ++f[a[i]];
    }
    for (int i=0; i<n; ++i) {
        if (f.count(a[i])&&f[a[i]]<2) f.erase(a[i]);
    }
    if (f.empty()) return puts("0"),0;
    if (f.size()==1) {
        if (f.begin()->second>=4) printf("%lld
", f.begin()->first*(int64_t)f.begin()->first);
        else puts("0");
        return 0;
    }
    int64_t ma = 0;
    for (auto &t:f) {
        if (t.second>=4) ma = max(ma, t.first*(int64_t)t.first);
    }
    int x = f.rbegin()->first;
    f.erase(x);
    int y = f.rbegin()->first;
    ma = max(ma, x*(int64_t)y);
    printf("%lld
", ma);
}
View Code

Coloring Dominoes

简单dp

#include <bits/stdc++.h>
using namespace std;
const int N = 55, P = 1000000007;
int n,dp[N];
char s[N],t[N];
int main() {
    scanf("%d%s%s", &n, s+1, t+1);
    int p;
    if (s[1]==t[1]) dp[1] = 3, p = 2;
    else dp[2] = 6, p = 3;
    for (int i=p; i<=n; ++i) {
        if (s[i]==t[i]) {
            if (s[i-1]==t[i-1]) {
                dp[i] = dp[i-1]*2%P;
            }
            else dp[i] = dp[i-1];
        }
        else {
            if (s[i-1]==t[i-1]) {
                dp[i+1] = dp[i-1]*2%P;
            }
            else {
                dp[i+1] = dp[i-1]*3ll%P;
            }
            ++i;
        }
    }
    printf("%d
", dp[n]);
}
View Code

Don't Be a Subsequence

关键要注意到如果$A$可以分成$x$个不相交的区间使得每个区间包含$[a,z]$所有字符,那么答案长度一定$>x$,所以可以贪心处理出每个后缀的答案,再枚举前缀贪心

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int nxt[N][26],ans[N];
char s[N], t[N];
int main() {
    scanf("%s", s+1);
    int n = strlen(s+1);
    set<char> mp;
    ans[n+1] = 1;
    for (int i=n; i; --i) {
        memcpy(nxt[i],nxt[i+1],sizeof nxt[0]);
        nxt[i][s[i]-'a'] = i;
        mp.insert(s[i]);
        ans[i] = ans[i+1];
        if (mp.size()==26) ++ans[i],mp.clear();
    }
    int now = 1;
    for (int i=1; i<=ans[1]; ++i) {
        for (char x='a'; x<='z'; ++x) {
            if (!nxt[now][x-'a']||ans[nxt[now][x-'a']+1]==ans[1]-i) {
                putchar(x);
                now = nxt[now][x-'a']+1;
                break;
            }
        }
    }
    puts("");
}
View Code

Flip and Rectangles

先考虑什么样的矩形是合法的,可以发现如果一个矩形每一列都和前一列相同或全相反,那么合法

所以先预处理出相同或相反的最大高度,然后悬线法即可

#include <bits/stdc++.h>
using namespace std;
const int N = 2e3+10;
int n, m, h[N][N][2];
char s[N][N];
pair<int,int> a[N];
int main() {
    scanf("%d%d", &n, &m);
    for (int i=1; i<=n; ++i) scanf("%s", s[i]+1);
    for (int j=2; j<=m; ++j) {
        for (int i=1; i<=n; ++i) {
            if (s[i][j-1]==s[i][j]) { 
                h[i][j][0] = h[i-1][j][0]+1;
                h[i][j][1] = 0;
            }
            else {
                h[i][j][1] = h[i-1][j][1]+1;
                h[i][j][0] = 0;
            }
        }
    }
    int ans = n;
    for (int i=1; i<=n; ++i) {
        int top = 0;
        a[++top] = {0,0};
        for (int j=1; j<=m+1; ++j) {
            int w = max(h[i][j][0], h[i][j][1]);
            if (w>=a[top].first) a[++top] = {w,j};
            else {
                while (top&&w<a[top].first) {
                    ans = max(ans, (j-a[top].second+1)*a[top].first);
                    --top;
                }
                a[++top].first = w;
            }
        }
    }
    printf("%d
", ans);
}
View Code
原文地址:https://www.cnblogs.com/fs-es/p/14016531.html