20200205DLUT寒假训练赛div2-codeforcesABC*3
A - Equator
记录前缀和,用库函数lower_bound找到第一个大于等于总和一半的位置(注意向上取整)
#include<cstdio>
#include<algorithm>
using namespace std;
long long t[200005];
int main(void)
{
int n, a;
scanf("%d", &n);
scanf("%lld", &t[0]);
for (int i = 1; i < n; ++i)
{
scanf("%d", &a);
t[i] = t[i - 1] + a;
}
printf("%d", lower_bound(t, t + n, (t[n - 1] + 1) / 2) - t + 1);
}
B - Students in Railway Carriage
引用二者中较大者和最小者,每次遇到空座位从最大者开始坐(针对奇数个空座位),cnt记录坐下的人数
#include<cstdio>
#include<algorithm>
using namespace std;
char p[200005];
int main(void)
{
int n, a, b, cnt = 0;;
scanf("%d%d%d", &n, &a, &b);
scanf("%s", p);
int i = 0;
while(i<n)
{
if (p[i] == '.')
{
int& mx = a > b ? a : b;
int& mi = a <= b ? a : b;
bool t = 0;
while (p[i] == '.')
{
if (t && mi)
{
--mi;
++cnt;
}
else if (!t && mx)
{
++cnt;
--mx;
}
t = 1 - t;
++i;
}
}
else
++i;
}
printf("%d", cnt);
}
C - Make a Square
bfs枚举数字的删除情况,mask二进制去记录每个位置的是否存在,1代表存在,0代表不存在,定义一个判断函数,如果mask为0则返回0,或者有前导0的话也返回0
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
char num[12];
int len;
int vis[1000000];
struct T
{
int steps, mask;
}p, t, q[1000000];
bool check(int m)
{
if (!m)
return 0;
int n = 0, flag = 0;
for (int i = 0; i < len; ++i)
{
if (m & (1 << i))
{
if (num[i] - '0')
flag = 1;
if (!flag && num[i] - '0' == 0)
return 0;
n = n * 10 + num[i] - '0';
}
}
int d = sqrt(n);
if (d * d == n)
return 1;
else
return 0;
}
int main(void)
{
bool flag = 0;
scanf("%s", num);
len = strlen(num);
int l = 0, r = 0, m = 0;
for (int i = 0; i < len; ++i)
m |= 1 << i;
vis[m] = 1;
t.mask = m;
q[r++] = t;
while (l < r && !flag)
{
p = q[l];
if (check(p.mask))
{
printf("%d", p.steps);
flag = 1;
break;
}
++l;
++p.steps;
for (int i = 0; i < len; ++i)
{
t = p;
t.mask &= (~(1 << i));
if (vis[t.mask]) continue;
vis[t.mask] = 1;
q[r++] = t;
}
}
if (!flag)
printf("-1");
}
D - Mind the Gap
将时间化成分钟,从小到大排序,判断相邻两个飞机起飞间隔是否大于2*s+1(要有加1,因为飞机起飞完后的1分钟后下一趟飞机才可以起飞),并且考虑该飞机第一个起飞和在最后一个位置起飞的特殊情况
#include<cstdio>
#include<algorithm>
using namespace std;
int t[105];
int main(void)
{
int n, s,a,b;
scanf("%d%d", &n,& s);
for (int i = 0; i < n; ++i)
{
scanf("%d%d", &a, &b);
t[i] = a * 60 + b;
}
sort(t, t + n);
if (t[0] > s)
printf("0 0");
else
{
int i;
for (i = 1; i < n; ++i)
{
if (t[i] - t[i - 1] > 2 * s + 1)
{
t[i - 1] += s + 1;
printf("%d %d", t[i - 1] / 60, t[i - 1] % 60);
break;
}
}
if (i == n)
printf("%d %d", (t[n - 1] + s + 1) / 60, (t[n - 1] + s + 1) % 60);
}
}
E - Watering System
每次是从第一个口出水,因此从大到小排序2到n个口,读入数据期间记录总口径和sum,如果出水量大于等于所需量跳出循环,每次循环期间维护sum
#include<cstdio>
#include<algorithm>
using namespace std;
int hole[100000];
const double eps = 1e-9;
bool cmp(int a, int b)
{
return a > b;
}
int main(void)
{
int n, a, b, sum = 0, cnt = 0;
scanf("%d%d%d", &n, &a, &b);
for (int i = 0; i < n; ++i)
{
scanf("%d", &hole[i]);
sum += hole[i];
}
sort(hole + 1, hole + n, cmp);
while (a * hole[0] * 1.0 / sum + eps < b && cnt < n - 1)
{
sum -= hole[cnt + 1];
++cnt;
}
printf("%d", cnt);
}
F - Stairs and Elevators
问题在于如何完成上下动作,因此每次去寻找离电梯和楼梯最近的两个点,算出四个点的最小值即为答案,并且要考虑如果在同一楼层直接走过去即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int l[100005], e[1000005];
int main(void)
{
int n, m, cl, ce, v, q, x[2], y[2];
scanf("%d%d%d%d%d", &n, &m, &cl, &ce, &v);
for (int i = 0; i < cl; ++i)
scanf("%d", &l[i]);
for (int i = 0; i < ce; ++i)
scanf("%d", &e[i]);
sort(l, l + cl);
sort(e, e + ce);
scanf("%d", &q);
while (q--)
{
scanf("%d%d%d%d", &y[0], &x[0], &y[1], &x[1]);
if (y[0] == y[1])
printf("%d\n", abs(x[1] - x[0]));
else
{
int te, tl, m[4] = { 0x3fffffff,0x3fffffff ,0x3fffffff ,0x3fffffff };
te = lower_bound(e, e + ce, x[0]) - e;
tl = lower_bound(l, l + cl, x[0]) - l;
if (te < ce)
m[0] = abs(e[te] - x[0]) + abs(e[te] - x[1]) + ceil(abs(y[0] - y[1]) * 1.0 / v);
if (tl < cl)
m[1] = abs(l[tl] - x[0]) + abs(l[tl] - x[1]) + abs(y[0] - y[1]);
if (te>0)
m[2] = abs(e[te - 1] - x[0]) + abs(e[te - 1] - x[1]) + ceil(abs(y[0] - y[1]) * 1.0 / v);
if (tl>0)
m[3] = abs(l[tl - 1] - x[0]) + abs(l[tl - 1] - x[1]) + abs(y[0] - y[1]);
int min = m[0];
for (int i = 1; i < 4; ++i)
min = min < m[i] ? min : m[i];
printf("%d\n", min);
}
}
}
G - Minimum Binary Number
记录字符串中0和1出现的数目,考虑1没出现过全是0的特殊情况(此时答案为0),输出一个1以及所有的0(无论多少个1最后都可以转化成1个1,但要放在最前面,不能有前缀0出现)
#include<cstdio>
#include<algorithm>
using namespace std;
char num[105];
int a[2];
int main(void)
{
int n;
scanf("%d", &n);
scanf("%s", num);
for (int i = 0; i < n; ++i)
{
if (num[i] == '0')
++a[0];
else
++a[1];
}
if (!a[1] && a[0])
printf("0");
else
{
printf("1");
for (int i = 0; i < a[0]; ++i)
printf("0");
}
}
H - Lara Croft and the New Game
考虑是否还在第一列的特殊情况,其他的相当于在一个矩形内逐层上升,分为奇数类和偶数类讨论,讨论期间同样要考虑是否整除的特殊情况
#include<cstdio>
#include<algorithm>
using namespace std;
int main(void)
{
long long int n, m, k;
scanf("%lld%lld%lld", &n, &m, &k);
if (k <= n - 1)
{
printf("%lld 1", 1 + k);
}
else
{
long long int x = k - n + 1;
long long int l = x / (m - 1);
long long int h = x % (m - 1);
if (l & 01)
{
if (h)
printf("%lld %lld", n - l, m + 1 - h);
else
printf("%lld %lld", n - l + 1, m);
}
else
{
if (h)
printf("%lld %lld", n - l, 1 + h);
else
printf("%lld %lld", n - l + 1, 2LL);
}
}
}
I - Nested Segments
将所给端点的左端点从小到大排序,右端点从大到小排序,如此只需要查看所有数据中是否有后一个数据被包含于前一个数据的情况,即可判断是否存在
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
struct T
{
int l, r;
int num;
}t[300005];
bool cmp(T a, T b)
{
if (a.l != b.l)
return a.l < b.l;
return a.r > b.r;
}
int main(void)
{
int n;
bool flag = 1;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
scanf("%d%d", &t[i].l, &t[i].r);
t[i].num = i + 1;
}
sort(t, t + n, cmp);
for (int i = 1; i < n; ++i)
{
if (t[i].r <= t[i - 1].r)
{
printf("%d %d", t[i].num, t[i - 1].num);
flag = 0;
break;
}
}
if (flag)
printf("-1 -1");
}
有一些小错误没注意,喜得wa下次得注意