昨天因为沈阳场真的去不成了,心态有点爆炸,就鸽了一天。而当鸽子是有代价的,所以今晚搞不好还有一场。
打的并不是很开心,T3的字典序想了好久也没弄出来,T4的悬线法太久没写,脑补的时候差点给我人送走。
赛中三题然后跑路了。
C:
开个map记录一下出现至少2、4次的最大次大值,然后判一判就完了。
#include<bits/stdc++.h>
using namespace std;
int num[200010];
int tnum[200010], fnum[200010];
int n, tcnt, fcnt;
int tma, tmm, foma;
map<int, int>sth;
int main() {
scanf("%d", &n);
for(int i=1;i<=n;++i)
scanf("%d", &num[i]), sth[num[i]]++;
for(int i=1;i<=n;++i) {
int nw = num[i];
if(sth[nw] >= 4) {
foma = max(foma, nw);
}
if(sth[nw] >= 2) {
tma = max(tma, nw);
}
}
for(int i=1;i<=n;++i) {
int nw = num[i];
if(sth[nw] >= 2 && nw != tma) {
tmm = max(tmm, nw);
}
}
long long ans = max(1ll * foma * foma, 1ll * tmm * tma);
cout<<ans;
return 0;
}
D:
发觉他并不会有图中左边这种情况,那么单独考虑一列,要么是一块,要么是两块。
记录一下每个地方到底是一块竖着的还是两块拼起来,判一判乘一乘就完事了。
#include<bits/stdc++.h>
using namespace std;
char s[3][100];
int n;
const int mod = 1000000007;
int trans[310], loc;
int main() {
scanf("%d", &n);
scanf("%s", s[1] + 1);
scanf("%s", s[2] + 1);
for(int i=1;i<=n;) {
if(s[1][i] == s[2][i]) {
trans[++loc] = 1;
++i;
continue;
}
if(s[1][i] != s[2][i]) {
trans[++loc] = 2;
i+=2;
continue;
}
}
long long ans = 1;
if(trans[1] == 1)
ans = 3;
else
ans = 6;
for(int i=2;i<=n;++i) {
int pre = trans[i-1], nw = trans[i];
if(pre == 1 && nw == 1) {
ans = ans * 2;
ans %= mod;
}
else if(pre == 2 && nw == 1) {
ans = ans * 1;
ans %= mod;
}
else if(pre == 1 && nw == 2) {
ans = ans * 2;
ans %= mod;
}
else if(pre == 2 && nw == 2) {
ans = ans * 3;
ans %= mod;
}
}
cout<<ans;
return 0;
}
E题:
判长度很好办,直接开个桶for过去,一轮一轮取就好。
但是字典序最小emmm,想了很久都没救,就弃疗去看F了。
题解爸爸表示,知道了长度并没有什么卵用,你需要观察出这玩意满足最优子结构。
令
p
o
s
[
i
]
[
j
]
pos[i][j]
pos[i][j]为,从
i
i
i位置开始往右看,字母
j
j
j第一次出现的位置下标。
状态为
d
p
[
i
]
dp[i]
dp[i]表示,在长度为
[
i
,
n
]
[i, n]
[i,n]这个后缀里面,不在里面的子序列的长度。
转移:
d
p
[
i
]
=
m
i
n
(
d
p
[
p
o
s
[
i
]
[
j
]
+
1
]
+
1
)
dp[i] = min(dp[pos[i][j]+1]+1)
dp[i]=min(dp[pos[i][j]+1]+1)
字典序:从
d
p
[
1
]
dp[1]
dp[1]for下去,每次找到最靠前,值对得上的转移走过去,输出就完事。
#include<bits/stdc++.h>
using namespace std;
char s[200010];
int pos[200010][140];
int dp[200010];
int n;
int main() {
scanf("%s", s+1);
n = strlen(s+1);
memset(pos,0x3f,sizeof(pos));
for(int i=n;i>=1;--i) {
for(int j='a';j<='z';++j)
pos[i][j] = pos[i+1][j];
pos[i][s[i]] = i;
}
for(int i=n+1;i<=n+5;++i)
dp[i] = 1;
for(int i=n;i>=1;--i) {
dp[i] = 0x3f3f3f3f;
for(int j='a';j<='z';++j) {
int tar = pos[i][j];
if(tar > n) {
dp[i] = 1;
break;
}
else
dp[i] = min(dp[i], dp[tar+1] + 1);
}
}
int nw = 1;
while(nw <= n) {
for(int i='a';i<='z';++i) {
int tar = pos[nw][i];
if(tar > n || dp[tar + 1] == dp[nw] - 1) {
printf("%c", i);
nw = tar + 1;
break;
}
}
}
return 0;
}
F题:
拿到之后感觉完全没想法,冷静了一下然后开始搞性质。
首先显然翻转的先后顺序没啥关系,一个格子只由他对应的行和列决定状态。
其次,容易发现,如果一个
2
×
2
2\times2
2×2的矩形里头有奇数个某种颜色,那么他铁定不可能全黑(奇偶性),称之为非法。
再其次,如果对于某一坨块儿矩形,它内部的每个
2
×
2
2\times2
2×2都不非法,那么肯定有办法让整个矩形全黑,这里考虑一个异或方程组的解就好,简单手玩了几组,也都有这个结论。
然后把每个
2
×
2
2\times2
2×2的左上角作为代表元,跑最大全
1
1
1矩形。
就是这悬线法,直接写没了我半条命。貌似上次写这玩意还是高二?
凭借模糊的远古记忆现场脑补算法.jpg
#include<bits/stdc++.h>
using namespace std;
int mat[2010][2010];
bool vis[2010][2010];
int lef[2010][2010], rig[2010][2010], upto[2010][2010];
char s[12313];
int n, m;
int main() {
scanf("%d%d", &n, &m);
for(int i=1;i<=n;++i) {
scanf("%s", s+1);
for(int j=1;j<=m;++j) {
mat[i][j] = s[j] == '#';
}
}
for(int i=1; i < n; ++i)
for(int j=1; j < m; ++j)
vis[i][j] = mat[i][j] ^ mat[i+1][j] ^ mat[i][j+1] ^ mat[i+1][j+1];
for(int i = 1; i < n; ++i) {
for(int j = 1; j < m; ++j)
lef[i][j] = vis[i][j] == 0 ? lef[i][j-1] + 1 : 0;
for(int j = m - 1; j >= 1; --j)
rig[i][j] = vis[i][j] == 0 ? rig[i][j+1] + 1 : 0;
}
int ans = max(n, m);
for(int j=0;j<=m;++j)
lef[0][j] = rig[0][j] = 123123;
// for(int i=1;i<n;++i) {
// for(int j=1;j<m;++j) {
// printf("%3d ", lef[i][j]);
// }
// printf("\n");
// }
// printf("\n");
// for(int i=1;i<n;++i) {
// for(int j=1;j<m;++j) {
// printf("%3d ", rig[i][j]);
// }
// printf("\n");
// }
// printf("\n");
for(int i = 1; i < n; ++i) {
for(int j = 1; j < m; ++j) {
if(vis[i][j]) {
upto[i][j] = 0;
lef[i][j] = rig[i][j] = 1231231;
}
else {
upto[i][j] = upto[i-1][j] + 1;
lef[i][j] = min(lef[i][j], lef[i-1][j]);
rig[i][j] = min(rig[i][j], rig[i-1][j]);
ans = max(ans, (upto[i][j] + 1) * (lef[i][j] + rig[i][j]));
}
}
}
cout<<ans;
return 0;
}