掉了点分
A:
给定长度为(2n-1)的01字符串(str),求长度为(n)的字符串(ans),使得(ans sim str)。
定义字符串(a sim b)时,有(i)满足(a_i = b_i)。
一道ca大水题,有两种解法:
-
/* ID: Loxilante Time: 2020/08/27 Prog: CF1400A-1 Lang: cpp */ #ifdef ONLINE_JUDGE #pragma GCC optimize("O3") #endif #include <bits/extc++.h> #define rep(i, l, r) for(int i = l; i < r; i++) #define hrp(i, l, r) for(int i = l; i <= r; i++) #define rev(i, r, l) for(int i = r; i >= l; i--) #define ms(n, t) memset(n, t, sizeof(n)) #define pb push_back #define int ll #ifndef JOEON #define D(...) 97 #endif using namespace std; typedef long long ll; typedef pair<int, int> pii; template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; } signed main(void) { clock_t Begin = clock(); #ifdef JOEON // freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin); // freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout); #endif ios::sync_with_stdio(false); cin.tie(0); int T = next(); clock_t InputFinished = clock(); while(T--) { int n = next(); string str = next<string>(); rep(i, 0, n) cout<<str[n-1]; cout<<endl; } clock_t End = clock(); D((double)(End-Begin)/CLOCKS_PER_SEC); D((double)(End-InputFinished)/CLOCKS_PER_SEC); return 0; }
-
/* ID: Loxilante Time: 2020/08/25 Prog: CF1400A Lang: cpp */ #ifdef ONLINE_JUDGE #pragma GCC optimize("O3") #endif #include <bits/extc++.h> #define rep(i, l, r) for(int i = l; i < r; i++) #define hrp(i, l, r) for(int i = l; i <= r; i++) #define rev(i, r, l) for(int i = r; i >= l; i--) #define ms(n, t) memset(n, t, sizeof(n)) #define pb push_back #define int ll #ifndef JOEON #define D(...) 97 #endif using namespace std; typedef long long ll; typedef pair<int, int> pii; template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; } signed main(void) { clock_t Begin = clock(); #ifdef JOEON // freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin); // freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout); #endif ios::sync_with_stdio(false); cin.tie(0); int T = next(); clock_t InputFinished = clock(); while(T--) { int l = next(); string str = next<string>(); for(int i = 0; i < str.length(); i += 2) cout<<str[i]; cout<<endl; } clock_t End = clock(); D((double)(End-Begin)/CLOCKS_PER_SEC); D((double)(End-InputFinished)/CLOCKS_PER_SEC); return 0; }
读者自证不难。
B:
你和随从分别能承重(p, f),现有(cnt_s)把剑和(cnt_w)把斧头,剑重(s),斧重(w),求最多能拿走多少武器。
考场上花一个小时打(O(1))算法,先(color{red}{PigeonGuGuGu})着。
下面来考虑(O(cnts))的做法:
假设(s <= w),也就是剑比斧重。
枚举自己最多带的剑的数量,算出能带斧的数量。
让随从带尽可能多的剑,如果带完了再带斧头。
Code:
/*
ID: Loxilante
Time: 2020/08/27
Prog: CF1400B
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next<int>();
clock_t InputFinished = clock();
while(T--)
{
int y, f, cnts, cntw, s, w, ans = 0;
cin>>y>>f>>cnts>>cntw>>s>>w;
if (s > w) swap(cnts, cntw), swap(s, w);
hrp(takeSword, 0, cnts)
{
if (takeSword*s > y) break;
int Y = y, F = f, ret = takeSword;
Y -= takeSword*s; // i take sword
int takeSword2 = min(F/s, cnts-takeSword); // follower take sword
ret += takeSword2;
F -= takeSword2*s;
ret += min(cntw, Y/w+F/w); // take war axe
ans = max(ans, ret);
}
cout<<ans<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
/*
3
33 27
6 10
5 6
100 200
10 10
5 5
1 19
1 3
19 5
*/
C:
考场上读假题,罚时杠杠哒
给定整数(x)和字符串(str),(str_i)等于(1)当且仅当(ans_{i+x})或(ans_{i-x})等于(0),求字符串(ans)。
1500的ca,对于这种ca我们可以直接口胡个greedy水过:
当(str_i)等于0时,我们让(ans_{i pm x} = 0),反正没有limit随便瞎搞,不过只有这些这题就配不上1500啦,难点还有(-1)。
不过这也很好操作,遍历(ans),然后判断是否合法,也就是(str_i = 1)时判断(ans_{i pm x})是否等于0,如果等于就输出(-1),1500的ca就是这么好水。
Code:
/*
ID: Loxilante
Time: 2020/08/26
Prog: CF1400C
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next();
clock_t InputFinished = clock();
while(T--)
{
string str = next<string>();
int x = next();
auto in = [=](const int& e)
{
return 0 <= e && e < str.length();
};
string ans;
rep(i, 0, str.length()) ans += '1';
rep(i, 0, str.length())
{
if (str[i] == '0')
{
int a = i-x, b = i+x;
if (in(a)) ans[i-x] = '0';
if (in(b)) ans[i+x] = '0';
}
}
bool N = 1;
rep(i, 0, str.size())
{
if (str[i] == '1')
{
bool no = 1;
int a = i-x, b = i+x;
if (in(a) && ans[a] == '1') no = 0;
if (in(b) && ans[b] == '1') no = 0;
if (no) {N = 0; break;}
}
}
if (!N) cout<<-1<<endl;
else cout<<ans<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
D:
超级1900大水题,可以用超级ez的dp水过,勉强算个dp吧。
给定数列(w),求满足(w_i == w_k && w_j == w_l (i < j < k < l))的个数。
考虑到(n <= 3000),可以用(O(n^2))的暴力枚举。
枚举谁呢? (i, j) ?不妥,(w_k)和(w_l)难求。(etc.)。感性推断,理性发现,只有枚举(w_k)和(w_j),这样(w_i)和(w_l)比较容易知道,也好写。
思路很简单:开一个(pr)前缀数组和(suf)后缀数组,(pr_{i,j})代表指针i之前等于(j)的个数,(suf_{i,j})代表指针i后等于(j)的个数,这大概也许应该是个dp吧,既然是dp,就得有个像样的转移方程,于是:
(pr_{i, j} = pr_{i-1, j} + (j == w[i]))
(suf_{i, j} = suf_{i+1, j} + (j == w[i]))
Code:
/*
ID: Loxilante
Time: 2020/08/26
Prog: CF1400D
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
const int U = 3e3+50;
int pr[U][U], suf[U][U], w[U];
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next();
clock_t InputFinished = clock();
while(T--)
{
int n = next(), ans = 0;
rep(i, 0, n) cin>>w[i];
ms(pr, 0);
ms(suf, 0);
rep(i, 0, n)
{
if (i) hrp(j, 0, n) pr[i][j] = pr[i-1][j];
pr[i][w[i]]++;
}
rev(i, n-1, 0)
{
if (i != n-1) hrp(j, 0, n) suf[i][j] = suf[i+1][j];
suf[i][w[i]]++;
}
rep(j, 1, n-2) rep(k, j+1, n-1) ans += pr[j-1][w[k]]*suf[k+1][w[j]];
cout<<ans<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
/*
Example
inputCopy
2
5
2 2 2 2 2
6
1 3 3 1 2 3
outputCopy
5
2
*/
然后我们发现,这个代码跑了1700ms,用了145000kb,大概是140mb,如果是128mb就要mle了,这时候我们可以压掉一个数组,把 (suf) 数组去掉,用类似前缀和的思想用大减小,这样就只有72000kb,也就是70mb。
Code:
/*
ID: Loxilante
Time: 2020/08/26
Prog: CF1400D
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
const int U = 3e3+50;
int pr[U][U], w[U];
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T = next();
clock_t InputFinished = clock();
while(T--)
{
int n = next(), ans = 0;
rep(i, 0, n) cin>>w[i];
ms(pr, 0);
rep(i, 0, n)
{
if (i) hrp(j, 0, n) pr[i][j] = pr[i-1][j];
pr[i][w[i]]++;
}
rep(j, 1, n-2) rep(k, j+1, n-1) ans += pr[j-1][w[k]]*(pr[n-1][w[j]]-pr[k][w[j]]);
cout<<ans<<endl;
}
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}
/*
Example
inputCopy
2
5
2 2 2 2 2
6
1 3 3 1 2 3
outputCopy
5
2
*/
E:
sharbee重题。
给定一个数列 (w),支持以下操作:
- 将([l, r])中的元素自减(1).
- 将(w_x)的元素自减(t).
求最少的操作次数,使数列w变为(0)。
先看题目,仔细一瞧,满足大问题分解成小问题的性质,这时候有两种选择,一是分治,二是dp,我选择分治,因为dp感觉有点难(
然后考虑分治函数,把一个大序列分解成左,右两个小序列,然后分别求解。
最后设计函数参数,首先begin, end是必不可少哒,其次我还设置了一个height,表示父问题中最小的元素的值。
Code:
/*
ID: Loxilante
Time: 2019/10/07
Prog: CF1400E
Lang: cpp
*/
#ifdef ONLINE_JUDGE
#pragma GCC optimize("O3")
#endif
#include <bits/extc++.h>
#define rep(i, l, r) for(int i = l; i < r; i++)
#define hrp(i, l, r) for(int i = l; i <= r; i++)
#define rev(i, r, l) for(int i = r; i >= l; i--)
#define ms(n, t) memset(n, t, sizeof(n))
#define pb push_back
#define int ll
#ifndef JOEON
#define D(...) 97
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
template<typename tn = int> inline tn next(void) { tn k; cin>>k; return k; }
const int U = 5e3+50;
int w[U];
inline int solve(int begin, int end, int height) // [, )
{
if (begin >= end) return 0;
int mid = min_element(w+begin, w+end)-w, ans; // 找到最小元素然后分治
ans = min(end-begin, solve(begin, mid, w[mid])+solve(mid+1, end, w[mid])+w[mid]-height);
// end-begin表示把每个元素都清0的个数
return ans;
}
signed main(void)
{
clock_t Begin = clock();
#ifdef JOEON
// freopen("C:\Users\Joeon\Desktop\IN.txt", "r", stdin);
// freopen("C:\Users\Joeon\Desktop\OUT.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int n = next();
rep(i, 0, n) cin>>w[i];
clock_t InputFinished = clock();
cout<<solve(0, n, 0)<<endl;
clock_t End = clock();
D((double)(End-Begin)/CLOCKS_PER_SEC);
D((double)(End-InputFinished)/CLOCKS_PER_SEC);
return 0;
}