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); }
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]); }
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(""); }
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); }