A-Bobo String Construction
题意 给定 01
串 t
,输出一个长度为 n
的 01
串 s
使得 t + s + t
中间只能找到 2 个 t
字符串
题解
- 如果
s
全为0
,只有以下情况使得条件不成立,此时若s
全为1
则满足条件 - 如果
t
全为1
,同上理,s
全为0
即可
00000|00000|00000
t s t
100001|0000|100001
t s t
100010|00|100010
t s t
010001|00|010001
t s t
1000100|0|1000100
t s t
以下是官方题解的证明:
暴力匹配
#include <iostream>
#define endl '\n'
using namespace std;
int n;
void solve() {
string t; cin >> n >> t;
string s(n, '0');
bool flag = 0;
string tst = t + s + t;
if (tst.find(t, 1) != t.size() + s.size()) flag = 1;
while (n --) cout << flag;
cout << endl;
}
int main() {
int T; cin >> T;
while (T --) solve();
return 0;
}
KMP 匹配
#include <iostream>
using namespace std;
const int N = 1e3 + 2;
int n, m, ne[N];
void solve() {
string t;
cin >> n >> t;
m = t.size();
string s(n, '0');
string tst = '0' + t + s + t;
t = '0' + t;
// 求 pmt
for (int i = 2, j = 0; i <= m; i ++) {
while (j && t[i] != t[j + 1]) j = ne[j];
if (t[i] == t[j + 1]) j ++;
ne[i] = j;
}
bool flag = false;
// 文本串匹配模式串
for (int i = 1, j = 0; i <= n + m * 2; i ++) {
while (j && tst[i] != t[j + 1]) j = ne[j];
if (tst[i] == t[j + 1]) j ++;
if (j == m && i != m && i != n + m * 2) {
flag = true;
break;
}
}
while (n --) cout << flag;
cout << endl;
}
int main() {
int T; cin >> T;
while (T --) solve();
return 0;
}
F-Election of the King
题意 n
个人,n - 1
轮投票,每次淘汰一个人,输出最后留下的人的下标。每次投票每个人选择和自己权值相差最大的,如果相同取全局最大的,最后如果出现平局,淘汰权值最大的人
题解 先排序,每次只能淘汰两端的,取首位的平均数,平均数之下的会投最右端的,平均数及其之上的会投最左端的,故比较平均数左右的人数,淘汰对应的人
#include <iostream>
#include <vector>
#include <algorithm>
#define endl '\n'
#define aa first
#define bb second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e6 + 2;
int n;
vector<pii> v;
int solve() {
cin >> n;
for (int i = 0; i < n; i ++) {
int x; cin >> x;
v.push_back({x, i + 1});
}
sort(v.begin(), v.end());
int l = 0, r = n - 1;
while (l < r) {
int ll = l, rr = r;
int x = v[ll].aa + v[rr].aa;
int y;
while (ll < rr) {
int mid = ll + rr >> 1;
y = v[mid].aa * 2;
if (y > x) rr = mid;
else ll = mid + 1;
}
ll --;
if (ll - l + 1 >= r - ll) r --;
else l ++;
}
return v[l].bb;
}
int main() {
cout << solve() << endl;
return 0;
}
J-Qu’est-ce Que C’est?
题意 求一个长度为 n
数序列,使得每个数的绝对值小于 m
,且任意长度不为 1
的区间的区间和非负,求有多少种满足的序列
Tag dp
状态表示
f
[
i
]
[
j
]
表示填了前
i
个数、后缀最小值为
j
的合法数量,
j
<
0
是可以的即表示最后一个数为负,且之前没有包括这个数负和区间
f[i][j]表示填了前i个数、后缀最小值为j的合法数量,j<0是可以的即表示最后一个数为负,且之前没有包括这个数负和区间
f[i][j]表示填了前i个数、后缀最小值为j的合法数量,j<0是可以的即表示最后一个数为负,且之前没有包括这个数负和区间
从 i − 1 个数转移,第 i 个数填 k ,从 f [ i − 1 ] [ j ] 转移到 f [ i ] [ m a x ( j , 0 ) + k ] 从i-1个数转移,第i个数填k,从f[i-1][j]转移到f[i][max(j,0)+k] 从i−1个数转移,第i个数填k,从f[i−1][j]转移到f[i][max(j,0)+k]
暂时无 code
L-We are the Lights
题意 每次选择一行或一列开或关灯,输出最后有多少灯开着
题解 结构体记录操作,只保留每行每列的最后一次操作,故每个点只能被改变两次
cnt
记录有多少行/列开灯,last
记录第几行/列的最后一次操作序号,st
记录每行/列最后的状态
操作 | res 变化 |
---|---|
行开 | + 关着的列 |
行关 | - 开着的列 |
列开 | + 关着的行 |
列关 | - 开着的行 |
#include <iostream>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N = 1e6 + 2;
ll l[2], cnt[2], last[2][N]; // 0row 1col
bool st[2][N]; // 0row 1col
struct Op {
bool type; // 0row 1col
int pos;
bool status; // 0off 1on
} ops[N];
ll solve() {
int q; cin >> l[0] >> l[1] >> q;
for (int i = 0; i < q; i ++) {
string s1, s2; int x; cin >> s1 >> x >> s2;
ops[i] = {s1 == "column", x, s2 == "on"};
st[s1 == "column"][x] = s2 == "on";
last[s1 == "column"][x] = i;
}
ll res = 0;
for (int i = 0; i < q; i ++) {
if (st[ops[i].type][ops[i].pos] ^ ops[i].status || i != last[ops[i].type][ops[i].pos]) continue;
if (ops[i].status) {
cnt[ops[i].type] ++;
res += l[1 - ops[i].type] - cnt[1 - ops[i].type];
}
else {
res -= cnt[1 - ops[i].type];
}
}
return res;
}
int main() {
cout << solve() << endl;
return 0;
}
法二:逆序操作,cnt
表示还剩多少行/列未被操作过,只要用 st
记录是否被操作过即可,操作过的 cnt --
#include <iostream>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N = 1e6 + 2;
ll n, m, cnt[2]; // 0row 1col
bool st[2][N]; // 0row 1col
struct Op {
bool type; // 0row 1col
int pos;
bool status; // 0off 1on
} ops[N];
ll solve() {
int q; cin >> n >> m >> q;
cnt[0] = n, cnt[1] = m;
for (int i = 0; i < q; i ++) {
string s1, s2; int x; cin >> s1 >> x >> s2;
ops[i] = {s1[0] == 'c', x, s2[1] == 'n'};
}
ll res = 0;
for (int i = q - 1; i >= 0; i --) {
if (st[ops[i].type][ops[i].pos]) continue;
st[ops[i].type][ops[i].pos] = true;
if (ops[i].status) res += cnt[1 - ops[i].type];
cnt[ops[i].type] --;
}
return res;
}
int main() {
cout << solve() << endl;
return 0;
}