AtCoder Beginner Contest 185
AtCoder Beginner Contest 185
A - ABC Preparation
Solution
输出最小值
#include
#include
using namespace std;
int main()
{
int a1, a2, a3, a4;
cin >> a1 >> a2 >> a3 >> a4;
cout << min(min(a1, a2), min(a3, a4)) << endl;
return 0;
}
B - Smartphone Addiction
Solution
模拟即可
#include
#include
#include
using namespace std;
int main()
{
int n, t, m, cap;
cin >> n >> m >> t; cap = n;
bool fl= true, wh = true;
int lt = 0;
for(int i = 0; i < m * 2; ++i) {
int mt; cin >> mt;
if(wh) {
n -= mt - lt;
}
else {
n += mt - lt;
}
n = min(n, cap);
if(n <= 0) fl = false;
wh = !wh;
lt = mt;
}
if(wh) {
n -= t - lt;
}
else {
n += t - lt;
}
n = min(n, cap);
if(n <= 0) fl = false;
cout << (fl ? "Yes" : "No") << endl;
return 0;
}
C - Duodecim Ferra
Solution
裁成12段,需要11个裁点,长为L裁点有L-1个,所以答案为\(C_{L-1}^{11}\),因为中间结果会long long
,所以用递推式计算:\(C_n^m=C_{n-1}^m+C_{n-1}^{m-1}\)
#include
#include
using namespace std;
typedef long long ll;
ll c[222][222];
int main()
{
ll l;
cin >> l;
l--;
for(int i = 0; i <= l; ++i) c[i][0] = c[i][i] = 1, c[i][1] = i;
for(int i = 1; i <= l; ++i) {
for(int j = 2; j < i; ++j) {
c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
}
}
cout << c[l][11] << endl;
return 0;
}
D - Stamp
Solution
找到最小的白色区间,即为最大可用stamp width,然后对每段计算需要几个stamp求和即可。
#include
#include
#include
using namespace std;
const int maxn = 211111;
int a[maxn];
int main()
{
int n, m; cin >> n >> m;
vector dis;
a[0] = 1;
for(int i = 1; i <= m; ++i) {
cin >> a[i];
}
a[m + 1] = n;
sort(a, a + m + 2);
int v = n;
for(int i = 2; i < m + 1; ++i) {
if(a[i] - a[i - 1] - 1 > 0) {
dis.push_back(a[i] - a[i - 1] - 1);
v = min(v, a[i] - a[i - 1] - 1);
}
}
if(m >= 1 && a[1] - a[0] > 0) {
dis.push_back(a[1] - a[0]);
v = min(v, a[1] - a[0]);
}
if(m >= 1 && n - a[m] > 0) {
dis.push_back(n - a[m]);
v = min(v, n - a[m]);
}
int ans = 0;
if(m == 0) ans = 1;
if(dis.size()) {
for(auto d : dis) {
ans += d / v;
if(d % v) ans++;
}
}
cout << ans << endl;
return 0;
}
E - Sequence Matching
Solution
直接套最小编辑距离的板子
#include
#include
using namespace std;
const int INF = 0x3f3f3f3f;
int dp[1005][1005]; /*dp[i][j]表示表示A串从第0个字符开始到第i个字符和B串从第0个字符开始到第j个字符,这两个字串的编辑距离。字符串的下标从1开始。*/
int a[1005],b[1005]; //a,b字符串从下标1开始
int n, m;
int EditDis()
{
int len1 = n;
int len2 = m;
//初始化
for(int i=1;i<=len1;i++)
for(int j=1;j<=len2;j++)
dp[i][j] = INF;
for(int i=1;i<=len1;i++)
dp[i][0] = i;
for(int j=1;j<=len2;j++)
dp[0][j] = j;
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
int flag;
if(a[i]==b[j])
flag=0;
else
flag=1;
dp[i][j]=min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+flag));
//dp[i-1][j]+1表示删掉字符串a最后一个字符a[i]
//dp[i][j-1]+1表示给字符串添加b最后一个字符
//dp[i-1][j-1]+flag表示改变,相同则不需操作次数,不同则需要,用flag记录
}
}
return dp[len1][len2];
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; ++i) cin >> a[i];
for(int j = 1; j <= m; ++j) cin >> b[j];
cout << EditDis() << endl;
return 0;
}
F - Range Xor Query
Solution
线段树裸题,由于处理的是异或运算,所以树状数组同样可以求解,亲测效率更高。
线段树版本:
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 1111111;
ll tree[maxn], n, q, arr[maxn];
void build(int ad, int l, int r)
{
if(l == r) {
tree[ad] = arr[l];
return;
}
int mid = (l + r) >> 1;
build(ad << 1, l, mid);
build(ad << 1 | 1, mid + 1, r);
tree[ad] = tree[ad << 1] ^ tree[ad << 1 | 1];
return;
}
void change(int ad, int l, int r, int d, ll ch)
{
if(l == r) {
if(l == d) {
tree[ad] = tree[ad] ^ ch;
}
return;
}
int mid = (l + r) >> 1;
if(mid >= d) {
change(ad << 1, l, mid, d, ch);
}
else {
change(ad << 1 | 1, mid + 1, r, d, ch);
}
tree[ad] = tree[ad << 1] ^ tree[ad << 1 | 1];
return;
}
ll query(int ad, int l, int r, int ql, int qr)
{
if(r < ql || l > qr) return 0;
if(l >= ql && r <= qr) return tree[ad];
int mid = (l + r) >> 1;
ll ans = 0;
if(mid >= ql) {
ans = ans ^ query(ad << 1, l, mid, ql, qr);
}
if(mid < qr) {
ans = ans ^ query(ad << 1 | 1, mid + 1, r, ql, qr);
}
return ans;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> q;
for(int i = 1; i <= n; ++i) cin >> arr[i];
build(1, 1, n);
while(q--) {
ll t, x, y;
cin >> t >> x >> y;
if(t == 1) {
change(1, 1, n, x, y);
}
else {
cout << query(1, 1, n, x, y) << endl;
}
}
return 0;
}
树状数组版本:
#include
#include
using namespace std;
inline int lowbit(int x) { return (x & (-x)); }
typedef long long ll;
const int maxn = 1111111;
ll tree[maxn], arr[maxn], n, q;
void update(int ad, ll x) {
while(ad <= n) {
tree[ad] = tree[ad] ^ x;
ad += lowbit(ad);
}
return;
}
ll query(int ad) {
ll ans = 0;
while(ad) {
ans ^= tree[ad];
ad -= lowbit(ad);
}
return ans;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> q;
for(int i = 1; i <= n; ++i) {
cin >> arr[i];
update(i, arr[i]);
}
while(q--) {
ll t, x, y;
cin >> t >> x >> y;
if(t == 1) {
update(x, y);
}
else {
cout << (query(y) ^ query(x - 1)) << endl;
}
}
return 0;
}
对于两种方式都可以的题,更喜欢用树状数组写,毕竟码量少,不容易出错==。