A - String Similarity
可以发现,string里面的最后一位每一次都会被遍历到,所以将res全部变成最后一位即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int T, n;
char s[101];
int main() {
T = read();
while (T--) {
n = read();
cin >> s;
char c = s[n - 1];
upd(i, 0, n - 1)printf("%c", c);
cout << endl;
}
return 0;
}
B - RPG Protagonist
贪心。枚举一个人选取的S或者W,那么另外一个就可以贪心的计算出来。
对于另外一个人而言,他应该优先选取更小的那一个。还需要动态维护两个数量。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e5 + 10;
int T;
ll p, f;
ll cnts, cntw;
ll s, w;
int main() {
T = read();
while (T--) {
p = read(), f = read();
if (p < f)swap(p, f);
cnts = read(), cntw = read();
s = read(), w = read();
if (s > w) {
swap(cnts, cntw);
swap(s, w);
}
ll ans = 0;
upd(i, 0, cnts) {
ll need = i * s;
if (need > p)break;
ll temp = i;
ll temp2 = (p - need) / w;
temp += temp2;
ll temp3 = min(f / s, cnts - i);
ll temp4 = min(cntw - temp2, (f - temp3 * s) / w);
temp += temp3 + temp4;
ans = max(ans, temp);
}
cout << ans << endl;
}
return 0;
}
C - Binary String Reconstruction
关注答案字符串中0的位置,他只能由左右两边同时为0构成。所以我们优先处理0的位置,并且将其他剩余位置全部赋值成1。最后在计算一次是否符合题意。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e5 + 10;
int T;
int x;
char s[N];
char res[N];
bool check(int n) {
upd(i, 1, n) {
if (s[i] == '1') {
bool flag1 = 0;
if (i - x >= 1) {
if (res[i - x] == '1')flag1 = 1;
}
if (i + x <= n)if (res[i + x] == '1')flag1 = 1;
if (flag1 == 0)return 0;
}
}
return 1;
}
int main() {
T = read();
while (T--) {
int n;
scanf("%s", s + 1);
n = strlen(s + 1);
upd(i, 0, n)res[i] = 0;
x = read();
upd(i, 1, n) {
if (s[i] == '0') {
res[max(0, i - x)] = '0';
res[min(n + 1, i + x)] = '0';
}
}
upd(i, 1, n)if (res[i] == 0)res[i] = '1';
res[n + 1] = '\0';
if (check(n)) {
printf("%s\n", res + 1);
}
else printf("%d\n", -1);
}
}
D - Zigzags
枚举
i
i
i和
j
j
j,题目转换成找到
k
<
l
,
a
[
k
]
=
a
[
i
]
,
a
[
j
]
=
a
[
l
]
k<l,a[k]=a[i],a[j]=a[l]
k<l,a[k]=a[i],a[j]=a[l]。所以我们需要高效的查询,
j
j
j位置后面,满足题意的
p
a
i
r
(
k
,
l
)
pair(k,l)
pair(k,l)的数量。
令
s
u
m
[
i
]
[
j
]
sum[i][j]
sum[i][j]表示
a
[
i
′
]
=
=
i
,
a
[
j
′
]
=
=
j
a[i']==i,a[j']==j
a[i′]==i,a[j′]==j有多少对满足题意,我们从后往前枚举,不断维护该数组,就可以找到满足题意的
p
a
i
r
pair
pair。所以我们需要先预处理出,对于位置
i
i
i来说,(
n
x
t
[
i
]
[
a
[
j
′
]
]
nxt[i][a[j']]
nxt[i][a[j′]]表示
i
i
i后面值为
a
[
j
′
]
a[j']
a[j′])
i
i
i后面接的数字的数量。那么每一次转移就有:
s
u
m
[
a
[
i
+
1
]
]
[
j
]
+
=
n
x
t
[
i
+
1
]
[
j
]
sum[a[i+1]][j]+=nxt[i+1][j]
sum[a[i+1]][j]+=nxt[i+1][j]
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 3e3 + 10;
int T, n;
ll a[N];
ll nxt[N][N];
ll suf[N][N];
int main() {
T = read();
while (T--) {
n = read();
upd(i, 0, n + 1)upd(j, 0, n + 1)nxt[i][j] = suf[i][j] = 0;
upd(i, 1, n)a[i] = read();
dwd(i, n, 1) {
upd(j, 1, 3000) {
nxt[i][j] = nxt[i + 1][j];
}
nxt[i][a[i + 1]]++;
}
ll ans = 0;
dwd(i, n-1, 1) {
upd(j, 1, 3000)
suf[a[i + 1]][j] += nxt[i + 1][j];
dwd(j, i - 1, 1) {
ans += suf[a[j]][a[i]];
}
}
printf("%lld\n", ans);
}
return 0;
}
E - Clear the Multiset
如果对于一段区间
l
,
r
l,r
l,r,我们采用了操作1(整体减少1),那么一定会将最小值减少到0。不然的话不会比操作二更优秀。
所以我们发现,对于一段
l
,
r
l,r
l,r而言,答案最多是
r
−
l
+
1
r-l+1
r−l+1。进行操作1,将区间某一些位置变成0,这个时候我们得到了一些分开的单独的区间,利用分治,我们继续进入区间进行计算即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e3 + 10;
int a[N];
int n;
int dp(int l, int r) {
if (r < l)return 0;
int mn = 1e9 + 1;
int pos = 0;
upd(i, l, r)
{
if (mn > a[i]) {
mn = a[i]; pos = i;
}
}
upd(i, l, r)a[i] -= mn;
return min(dp(l, pos - 1) + dp(pos + 1, r) + mn, r - l + 1);
}
int main() {
n = read();
upd(i, 1, n) {
a[i] = read();
}
cout<<dp(1, n);
}
F - x-prime Substrings
预处理出,是x-prime的所有字符串。可以通过打表发现,最多2500个。插入到trie数中,最多10000个点。
题目转换成,给出一些字符串,在原串不能出现这些字符串。这就和ac自动机的一些裸题很类似了。(构建
t
r
i
e
trie
trie图)
令
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示,做到原字符串第
i
i
i位,在
t
i
r
e
tire
tire图上
j
j
j状态的最小代价。(
t
r
i
e
trie
trie图上任意状态都有转移状态)
如果有删除
d
p
[
i
+
1
]
[
j
]
=
m
i
n
(
d
p
[
i
+
1
]
[
j
]
,
d
p
[
i
]
[
j
]
+
1
)
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)
dp[i+1][j]=min(dp[i+1][j],dp[i][j]+1)
没有删除,并且下一个状态不是非法状态
d
p
[
i
+
1
]
[
j
′
]
=
m
i
n
(
d
p
[
i
+
1
]
[
j
′
]
,
d
p
[
i
]
[
j
]
)
(
j
′
=
t
i
r
e
.
c
h
[
j
]
[
s
[
i
]
−
′
0
]
)
dp[i+1][j']=min(dp[i+1][j'],dp[i][j])(j'=tire.ch[j][s[i]-'0])
dp[i+1][j′]=min(dp[i+1][j′],dp[i][j])(j′=tire.ch[j][s[i]−′0])
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1010;
vector<int>vec;
char s[N];
int x;
struct trie {
int ch[N * 10][15];
int flag[N * 10];
int fail[N * 10];
int cnt = 0;
void insert() {
/*for (auto k : vec)cout << k;
cout << endl;*/
int len = vec.size();
int root = 0;
up(i, 0, len) {
int c = vec[i];
if (!ch[root][c])
ch[root][c] = ++cnt;
root = ch[root][c];
}
//cout << this->cnt << endl;
flag[root] = 1;
}
void getfail() {
int root = 0;
fail[root] = -1;
queue<int>q;
up(i, 0, 10)
if (ch[root][i])q.push(ch[root][i]);
while (!q.empty()) {
int top = q.front();
q.pop();
up(i, 0, 10) {
int v = ch[top][i];
if (!v)ch[top][i] = ch[fail[top]][i];
else {
q.push(v);
fail[v] = ch[fail[top]][i];
flag[v] |= flag[fail[v]];
}
}
}
}
}T;
void dfs(int sum) {
if (sum > x)return;
if (sum == x) {
up(i, 0, vec.size()) {
int summ = 0;
dwd(j, i, 0) {
summ += vec[j];
if (summ != x) {
if (x%summ == 0)return;
}
}
}
T.insert();
return;
}
upd(i, 1, 9) {
vec.push_back(i);
dfs(sum + i);
vec.pop_back();
}
}
int dp[N][N * 10];
void test(int n) {
cout << T.cnt << endl;
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= T.cnt; ++j) {
printf("%d ", dp[i][j]);
}
cout << endl;
}
}
int main() {
cin >> s;
x = read();
dfs(0);
T.getfail();
int n = strlen(s);
memset(dp, INF, sizeof(dp));
dp[0][0] = 0;
up(i, 0, n) {
upd(j, 0, T.cnt) {
if (dp[i][j]>=INF)continue;
dp[i + 1][j] = min(dp[i + 1][j], dp[i][j] + 1);
int c = T.ch[j][s[i] - '0'];
if (T.flag[c])continue;
dp[i + 1][c] = min(dp[i + 1][c], dp[i][j]);
}
}
int ans = INF;
//test(n);
upd(j, 0, T.cnt)
ans = min(ans, dp[n][j]);
cout << ans << endl;
return 0;
}