Educational Codeforces Round 94 (Rated for Div. 2)
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\)和\(j\),題目轉換成找到\(k<l,a[k]=a[i],a[j]=a[l]\)。所以我們需要高效的查詢,\(j\)位置後面,滿足題意的\(pair(k,l)\)的數量。
令\(sum[i][j]\)表示\(a[i']==i,a[j']==j\)有多少對滿足題意,我們從後往前列舉,不斷維護該陣列,就可以找到滿足題意的\(pair\)。所以我們需要先預處理出,對於位置\(i\)來說,(\(nxt[i][a[j']]\)表示\(i\)後面值為\(a[j']\))\(i\)後面接的數字的數量。那麼每一次轉移就有:\(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\),我們採用了操作1(整體減少1),那麼一定會將最小值減少到0。不然的話不會比操作二更優秀。
所以我們發現,對於一段\(l,r\)而言,答案最多是\(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自動機的一些裸題很類似了。(構建\(trie\)圖)
令\(dp[i][j]\)表示,做到原字串第\(i\)位,在\(tire\)圖上\(j\)狀態的最小代價。(\(trie\)圖上任意狀態都有轉移狀態)
如果有刪除
\(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])(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;
}