2019.10.28 night 题解报告


2019.10.28 题解报告

答题情况:

  • 总成绩 : 90, 排名:52(名次) / 166(总人数)
  • T1 : 10 T2 : 50 T3 : 30

各题目分析:

  • 题目1:
    预估成绩 : 100 实际成绩 :10 考试用时 : 6:10 ~ 7:30

    开局刚T1, 细节繁琐的模拟, 耗时较长
    最后过掉了 给的两个样例, 就放下不管了
    最后爆炸了

    1. vector类最好少用, 容易导致未知的运行错误
    2. 过掉给的样例之后, 最好再手造几组样例,
      测试正确性, 也测试是否会运行错误
  • 题目2:
    预估成绩 : 40 实际成绩 : 50 考试用时 : 7:40 ~ 8:20

    先进行分析 , 之后写了暴力
    手造了 几组数据测试了一下正确性, 发现没有问题
    暴力没有写挂

  • 题目3:
    预估成绩 : 30 实际成绩 : 30 考试用时 : 8:30 ~ 9:10

    首先考虑 子任务1, 发现有一种n^2的做法, 可以拿到20分
    再考虑 对应数据范围的子任务2, 有一种n^4的区间DP可以写, 可以拿到 10分

    于是做了数据分治, 暴力没有写挂

题目解析:

T1:

60% 数据 :
枚举 T个时刻, 再枚举 两队的球员
暴力比较 贡献, 并进行替换
复杂度O((n + m) T);

80% 数据:
显然, 每次 (换下的队员能力 - 换上的队员能力) 一定比其他换人方案都小,
这样才能满足 每次上场的球员 能力值 最大

故, 可以先将各队队员 按照位置进行分类,
再对 每一类进行 按照 能力值降序排序

则可以按照上述规则, 将场上的队员 与 场下的队员进行替换

由于需要枚举每个时刻, 总复杂度 O(T)

100% 数据:
发现 根本不需要枚举每个时刻,
只需要枚举 需要换人的时刻即可

则可以枚举 p和q的倍数,
总复杂度O(T/p + T/q)


T2:

若有下列模型:
x1 x2 x3
a1 a2 a3

若要将x2, x3的积木都般至x1
有下列两种方案:

  1. 先将 x2般至 x1, 再将 x3 般至 x1
  2. 先将 x3般至 x2, 再将 x2 般至 x1

以上两种方案, 在时间充足情况下, 总耗时相同
但是在时间不足的情况下, 显然方案 1 更优.

50% 数据:
可枚举每一个位置, 并维护两个指针
分别将两侧 离得更近的元素 加入答案

总复杂度 O(n^2)

80% 数据:

发现枚举每一个位置p 是不可缺少的.
根据 得到的性质, 显然, 能够叠到枚举位置的 k个方块 ,
一定为 离枚举位置p 最近的 前k的方块

则可以 二分枚举 离枚举位置最远的, 能够叠到枚举位置的 方块的距离s
则问题转化为: 将距离s以内的所有方块 放到枚举位置, 花费总时间是否 > T

可以使用 二分查找 找到枚举位置左右两侧 距离 <= s 的最远位置, 记为 l,r
则需要求得 l,r 内方块的贡献:

\[\large \sum\limits_{i = l}^{r}{\mid x[i] - x[p] \mid \times a[i]} \]

将得到的式子 使用前缀和进行优化, 。则可以 O(1) 计算出贡献

总复杂度 O(n (logn) ^ 2)

100 % 数据:

当枚举位置 p 右移时,
二分查找 找到枚举位置左右两侧 距离 <= s 的最远位置 l,r 也单调右移
满足单调性.

则可以免去 每一次枚举位置时都进行二分查找
总复杂度 O(n logn)


T3:

30 % 数据:
对于 子任务1,
可以暴力枚举 每一个 长度为 4的倍数的串,
并暴力检查其是否合法

复杂度O(n ^ 2) 级别, 可以过 1000

对于子任务2, 可以进行区间DP
设状态: f[l][r] 表示 区间[l,r] 被覆盖需要多少串
显然, f[l][l] = 1,
对于 子任务一中 检查成功的 串, f[l][r] = 1

直接暴力转移:
f[l][r] = min(f[l][r], f[l][k] + f[k1][r]);

复杂度O(n^4), 可以过 100

100 % 数据:
nb manacher + nb segmenttree
咕了咕了


代码实现:

T1:

  • 考场代码:
//
/*
By:Luckyblock
*/
#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
#include <ctype.h>
#include <string>
#include <iostream>
#define ll long long
const int MARX = 1e5 + 10;
//=============================================================
struct person
{
	std :: string name, pos;
	int num, pow;
}A, B;
int N, M, T, P, Q, nowA[6], nowB[6];
std:: map <std :: string, int> m;
std:: vector <person> AA[6], BB[6];
//=============================================================
inline int read()
{
    int s=1, w=0; char ch=getchar();
    for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
    for(; isdigit(ch);ch=getchar()) w = (w << 1) + (w << 3) +ch-'0';
    return s*w;
}
bool cmp(person fir, person sec)
{
	if(fir.pow == sec.pow) return fir.num < sec.num;
	return fir.pow > sec.pow;
}
//=============================================================
signed main()
{
	freopen("match.in","r",stdin);
	freopen("match.out","w",stdout);
	m["pg"] = 1, m["sg"] = 2, m["sf"] = 3, m["pf"] = 4, m["c"] = 5;
	N = read(), M = read(), T = read(), P = read(), Q = read();
	for(int i = 1; i <= N; i ++)
	{
	  
	  std :: cin >> A.name;
	  std :: cin >> A.num;
	  std :: cin >> A.pos;
	  std :: cin >> A.pow;
	  AA[m[A.pos]].push_back(A);
	}
	
	for(int i = 1; i <= M; i ++)
	{
	  std :: cin >> B.name;
	  std :: cin >> B.num;
	  std :: cin >> B.pos;
	  std :: cin >> B.pow;
	  BB[m[B.pos]].push_back(B);
	}
	
	for(int i = 1; i < 6; i ++)
	{
	  std :: sort (AA[i].begin(), AA[i].end(), cmp);
	  std :: sort (BB[i].begin(), BB[i].end(), cmp);
	}
	
	int p = P, q = Q;
	for(int now = 0; now < T;)
	{
	  if(p < q) 
	  {
	  	now += p, q -= p, p = P;
	  	if(now >= T) break;
	  	
	  	int tar = 1;
	  	for(int i = 2; i <= 5; i ++)
	  	{
	  	  if(AA[tar].size() == nowA[tar] + 1) {tar = i; continue;}
	  	  if(AA[i].size() == nowA[i] + 1) continue;
	  	  
	  	  if(AA[i][nowA[i]].pow - AA[i][nowA[i] + 1].pow < AA[tar][nowA[tar]].pow - AA[tar][nowA[tar] + 1].pow) tar = i;
	  	  else if(AA[i][nowA[i]].pow - AA[i][nowA[i] + 1].pow == AA[tar][nowA[tar]].pow - AA[tar][nowA[tar] + 1].pow)
		    if(AA[i][nowA[i] + 1].num < AA[tar][nowA[tar] + 1].num) tar = i;
		}
	  	
		printf("Substitution by A,No.%d ", AA[tar][nowA[tar] + 1].num);
		std :: cout << AA[tar][nowA[tar] + 1].name;
		printf(" is coming up to change No.%d ", AA[tar][nowA[tar]].num);
		std:: cout << AA[tar][nowA[tar]].name << ".\n"; 
		
		nowA[tar] ++;
	  }
	  else if(p > q) 
	  {
	  	now += q, p -= q, q = Q;
	  	if(now >= T) break;
	  	
	  	int tar = 1;
	  	for(int i = 2; i <= 5; i ++)
	  	{
	  	  if(BB[tar].size() == nowB[tar] + 1) {tar = i; continue;}
	  	  if(BB[i].size() == nowB[i] + 1) continue;
	  	  
	  	  if(BB[i][nowB[i]].pow - BB[i][nowB[i] + 1].pow < BB[tar][nowB[tar]].pow - BB[tar][nowB[tar] + 1].pow) tar = i;
	  	  else if(BB[i][nowB[i]].pow - BB[i][nowB[i] + 1].pow == BB[tar][nowB[tar]].pow - BB[tar][nowB[tar] + 1].pow)
		    if(BB[i][nowB[i] + 1].num < BB[tar][nowB[tar] + 1].num) tar = i;
		}
	  	
		printf("Substitution by B,No.%d ", BB[tar][nowB[tar] + 1].num);
		std :: cout << BB[tar][nowB[tar] + 1].name;
		printf(" is coming up to change No.%d ", BB[tar][nowB[tar]].num);
		std:: cout << BB[tar][nowB[tar]].name << ".\n";
		
		nowB[tar] ++;
	  }
	  else 
	  {
	  	now += q, p = P, q = Q;
	  	if(now >= T) break;
	  	
	  	int tar = 1;
	  	for(int i = 2; i <= 5; i ++)
	  	{
	  	  if(AA[tar].size() == nowA[tar] + 1) {tar = i; continue;}
	  	  if(AA[i].size() == nowA[i] + 1) continue;
	  	  
	  	  if(AA[i][nowA[i]].pow - AA[i][nowA[i] + 1].pow < AA[tar][nowA[tar]].pow - AA[tar][nowA[tar] + 1].pow) tar = i;
	  	  else if(AA[i][nowA[i]].pow - AA[i][nowA[i] + 1].pow == AA[tar][nowA[tar]].pow - AA[tar][nowA[tar] + 1].pow)
		    if(AA[i][nowA[i] + 1].num < AA[tar][nowA[tar] + 1].num) tar = i;
		}
	  	
		printf("Substitution by A,No.%d ", AA[tar][nowA[tar] + 1].num);
		std :: cout << AA[tar][nowA[tar] + 1].name;
		printf(" is coming up to change No.%d ", AA[tar][nowA[tar]].num);
		std:: cout << AA[tar][nowA[tar]].name << ".\n"; 
		
		tar = 1;
	  	for(int i = 2; i <= 5; i ++)
	  	{
	  	  if(BB[tar].size() == nowB[tar] + 1) {tar = i; continue;}
	  	  if(BB[i].size() == nowB[i] + 1) continue;
	  	  
	  	  if(BB[i][nowB[i]].pow - BB[i][nowB[i] + 1].pow < BB[tar][nowB[tar]].pow - BB[tar][nowB[tar] + 1].pow) tar = i;
	  	  else if(BB[i][nowB[i]].pow - BB[i][nowB[i] + 1].pow == BB[tar][nowB[tar]].pow - BB[tar][nowB[tar] + 1].pow)
		    if(BB[i][nowB[i] + 1].num < BB[tar][nowB[tar] + 1].num) tar = i;
		}
		
		printf("Substitution by B,No.%d ", BB[tar][nowB[tar] + 1].num);
		std :: cout << BB[tar][nowB[tar] + 1].name;
		printf(" is coming up to change No.%d ", BB[tar][nowB[tar]].num);
		std:: cout << BB[tar][nowB[tar]].name << ".\n";
		
		nowA[tar] ++, nowB[tar] ++;;
	  }
	}
	
	return 0;
}
/*
8 8 9 3 4
LiMing 1 pg 80
LiGang 2 sg 80
LiQang 3 sf 80
LiNiu 4 pf 90
LiWen 5 c 90
LiXiang 6 pf 75
LiReng 7 pg 65
LiChun 8 sf 70
HuMing 1 pg 90
HuGang 2 sg 90
HuQang 3 sf 100
HuNiu 4 pf 80
HuWen 5 c 70
HuXiang 6 c 70
HuReng 7 pg 65
HuChun 8 sf 70
*/
/*
Substitution by A,No.8 LiChun is coming up to change No.3 LiQiang.
Substitution by B,No.6 HuXiang is coming up to change No.5 HuWen.
Substitution by A,No.6 LiXiang is coming up to change No.4 LiNiu.
Substitution by B,No.7 HuReng is coming up to change No.1 HuMing.
*/

  • 正解 :
#include<bits/stdc++.h>
using namespace std;
struct player {
	char name[16]; int num, score;
} a[2][5][500100];
int n, m, t, p, q, turn[2][5], sum[2][5], psum, qsum, num, score, team, pos;
char sname[16], spos[16];
bool cmp(player a, player b) {
	return (a.score == b.score ? a.num < b.num : a.score > b.score);
}
int main() {
	freopen("match.in", "r", stdin);
	freopen("match.out", "w", stdout);
	scanf("%d%d%d%d%d", &n, &m, &t, &p, &q);
	for (int i = 1; i <= n + m; i++) {
		team = (i <= n ? 0 : 1);
		scanf("%s %d %s %d", sname, &num, spos, &score);
		if (spos[0] == 'p' && spos[1] == 'g') pos = 0;
		if (spos[0] == 's' && spos[1] == 'g') pos = 1;
		if (spos[0] == 's' && spos[1] == 'f') pos = 2;
		if (spos[0] == 'p' && spos[1] == 'f') pos = 3;
		if (spos[0] == 'c') pos = 4;
		a[team][pos][++sum[team][pos]] = (player) {"", num, score};
		strcpy(a[team][pos][sum[team][pos]].name, sname);
	}
	for (int i = 0; i <= 4; i++) {
		sort(a[0][i] + 1, a[0][i] + sum[0][i] + 1, cmp);
		sort(a[1][i] + 1, a[1][i] + sum[1][i] + 1, cmp);
	}
	for (int i = 0; i <= 4; i++) turn[0][i] = turn[1][i] = 1;
	psum = 1, qsum = 1;
	while (p * psum < t || q * qsum < t) {
		if (p * psum <= q * qsum) team = 0, psum++; else team = 1, qsum++;
		int mn = 999, pm; player up, down;
		for (int i = 0; i <= 4; i++) {
			int k = turn[team][i], c = a[team][i][k].score - a[team][i][k + 1].score;
			if (k == sum[team][i]) continue;
			if (c < mn || (c == mn && a[team][i][k + 1].num < up.num))
				mn = c, pm = i, up = a[team][i][k + 1], down = a[team][i][k];
		}
		turn[team][pm]++;
		char ct = (team == 0 ? 'A' : 'B');
		printf("Substitution by %c,No.%d %s is coming up to change No.%d %s.\n", ct, up.num, up.name, down.num, down.name);
	}
	return 0;
}

T2:

  • 考场代码:
#include <cstdio>
#include <ctype.h>
#define int long long
#define max(a,b) (a > b ? a : b)
#define min(a,b) (a < b ? a : b)
const int MARX = 5e5 + 10;
//=============================================================
int n, t, ans, x[MARX], a[MARX];
//=============================================================
inline int read()
{
    int s=1, w=0; char ch=getchar();
    for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
    for(; isdigit(ch);ch=getchar()) w = (w << 1) + (w << 3) +ch-'0';
    return s*w;
}
//=============================================================
signed main()
{
	freopen("block.in","r",stdin);
	freopen("block.out","w",stdout);
	n = read(), t = read();
	for(int i = 1; i <= n; i ++) x[i] = read();
	for(int i = 1; i <= n; i ++) a[i] = read();
	for(int i = 1, sum  = a[i]; i <= n; i ++, sum = a[i])
	{
	  for(int l = i - 1, r = i + 1, nowt = t; nowt > 0; )
		if(l > 0 && r <= n)
		{
		  if(x[i] - x[l] < x[r] - x[i]) sum += min(a[l], nowt / (2 * (x[i] - x[l]))), nowt -= a[l] * (2 * (x[i] - x[l])), l --;
		  else sum += min(a[r], nowt / (2 * (x[r] - x[i]))), nowt -= a[r] * (2 * (x[r] - x[i])), r ++;
		}
		else if(l > 0)
		{
		  sum += min(a[l], nowt / (2 * (x[i] - x[l]))), nowt -= a[l] * (2 * (x[i] - x[l])), l --;
		}
		else if(r <= n)
		{
		  sum += min(a[r], nowt / (2 * (x[r] - x[i]))), nowt -= a[r] * (2 * (x[r] - x[i])), r ++;
		}
		else break;
	  ans = max(sum, ans);
	}
	
	printf("%I64d", ans);
}
  • 正解 :
#include<bits/stdc++.h>
#define N 500010
using namespace std;
typedef long long ll;
ll s[N], T;
int x[N], a[N], n;
bool check(ll H) {
	ll nowh = 0, tim = 0;
	int lc = 0, rc = 0, l = 1, r = n + 1;
	for (int i = 1; i <= n; i++)
		if (nowh + a[i] <= H) nowh += a[i], tim += (ll)(x[i] - x[1]) * a[i];
		else {r = i, rc = H - nowh, tim += (ll)(x[i] - x[1]) * rc; break;}
	if (tim <= T) return 1;
	for (int i = 2; i <= n; i++) {
		ll suml = s[i - 1] - s[l - 1] - lc;
		ll sumr = s[r - 1] - s[i - 1] + rc;
		tim += (x[i] - x[i - 1]) * (suml - sumr);
		while (r <= n && x[i] - x[l] > x[r] - x[i]) {
			int can = min(a[l] - lc, a[r] - rc);
			tim += (x[r] - x[i] - x[i] + x[l]) * can;
			lc += can, rc += can;
			if (lc >= a[l]) ++l, lc = 0;
			if (rc >= a[r]) ++r, rc = 0;
		}
		if (tim <= T) return 1;
	}
	return 0;
}
int main() {
	freopen("block.in", "r", stdin);
	freopen("block.out", "w", stdout);
	scanf("%d%I64d", &n, &T); T /= 2;
	for (int i = 1; i <= n; i++) scanf("%d", &x[i]);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];
	ll l = 0, r = s[n], ans;
	while (l <= r) {
		ll mid = (l + r) >> 1;
		if (check(mid)) l = mid + 1, ans = mid;
		else r = mid - 1;
	}
	printf("%I64d\n", ans);
	return 0;
}

T3:

  • 考场代码 :
//
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <cstring>
#define int long long
#define min(a,b) (a < b ? a : b)
const int MARX = 5e5 + 10;
//=============================================================
int lth, type, ans1, f[1010][1010];
char s[MARX];
//=============================================================
inline int read()
{
    int s=1, w=0; char ch=getchar();
    for(; !isdigit(ch);ch=getchar()) if(ch=='-') s =-1;
    for(; isdigit(ch);ch=getchar()) w = (w << 1) + (w << 3) +ch-'0';
    return s*w;
}
bool check(int L, int R, int size)
{
	for(int l = L, r = L + 2 * size - 1; l < r; l ++, r --)
	  if(s[l] != s[r]) return 0;
	for(int l = L + 2 * size, r = R; l < r; l ++, r --)
	  if(s[l] != s[r]) return 0;
	for(int l1 = L, l2 = L + 2 * size; l1 <= L + size - 1; l1 ++, l2 ++)
	  if(s[l1] != s[l2]) return 0;
	return 1;
}
//=============================================================
signed main()
{
	freopen("htstr.in","r",stdin);
	freopen("htstr.out","w",stdout);
	memset(f, 63, sizeof(f));
	scanf("%s", s + 1); lth = strlen(s + 1); ans1 = lth;
	type = read();
	
	for(int i = 1; i <= lth; i ++) f[i][i] = 1;	
	for(int i = 1; i <= (lth / 4); i ++)
	  for(int l = 1, r = l + 4 * i - 1; r <= lth; l ++, r ++)
	    if(check(l, r, i)) ans1 ++, f[l][r] = 1;
	printf("%I64d", ans1);
	
	if(type == 3)
	  for(int i = 2; i <= lth; i ++)
	    for(int l = 1, r = l + i - 1; r <= lth; l ++, r ++)
	      for(int k = l; k < r; k ++)
	        for(int k1 = l + 1; k1 <= k + 1; k1 ++)
		      f[l][r] = min(f[l][r], f[l][k] + f[k1][r]);
	
	if(type == 3) printf(" %I64d", f[1][lth]);	
}
  • 正解
 #include<bits/stdc++.h>
#define N 500010
#define ls (x << 1)
#define rs (x << 1 | 1)
using namespace std;
typedef long long ll;
struct intv{
	int s, i;
} a[N], b[N];
int p[N], rc[N << 2], f[N], n, m, type, anss, sum[N << 2];
ll ansf;
char s[N];
bool cmp(intv a, intv b) {
	return a.s < b.s;
}
inline void updata(int x, int l, int r, int p) {
	if (l == r) {
		rc[x] = r, sum[x] = 1; return;
	}
	int mid = (l + r) >> 1;
	if (p <= mid) updata(ls, l, mid, p);
	else updata(rs, mid + 1, r, p);
	sum[x] = sum[ls] + sum[rs];
	rc[x] = (rc[rs] == -1 ? rc[ls] : rc[rs]);
}
inline intv query(int x, int l, int r, int xl, int xr) {
	if (l == xl && r == xr) return (intv) {sum[x], rc[x]};
	int mid = (l + r) >> 1;
	if (xr <= mid) return query(ls, l, mid, xl, xr);
	else if (xl > mid) return query(rs, mid + 1, r, xl, xr);
	else {
		intv ql = query(ls, l, mid, xl, mid), qr = query(rs, mid + 1, r, mid + 1, xr);
		return (intv) {ql.s + qr.s, qr.i == -1 ? ql.i : qr.i};
	}
}
int main() {
	freopen("htstr.in", "r", stdin);
	freopen("htstr.out", "w", stdout);
	scanf("%s%d", s + 1, &type);
	n = strlen(s + 1); s[0] = '#';
	int mx = 0, id, now = 1;
	for (int i = 1; i <= n; i++) {
		if (mx >= i) p[i] = min(mx - i, p[2 * id - i]);
		for (; s[i + p[i] + 1] == s[i - p[i]]; p[i]++);
		if (p[i] + i < mx) id = i, mx = p[i] + i;
	}
	for (int i = 1; i <= n; i++) a[i] = (intv) {i - p[i], i};
	sort(a + 1, a + n + 1, cmp);
	for (int i = 1; i <= n << 2; i++) rc[i] = -1;
	for (int i = 1; i <= n; i++) {
		while (now <= n && a[now].s <= i) updata(1, 1, n, a[now].i), now++;
		if (p[i] <= 1) continue;
		intv qs = query(1, 1, n, i + 1, i + p[i] / 2);
		ansf += (ll)qs.s;
		if (qs.i != -1) b[++m] = (intv) {3 * i - 2 * qs.i + 1, 2 * qs.i - i};
	}
	if (type == 1) {printf("%I64d\n", ansf + n); return 0;}
	sort(b + 1, b + m + 1, cmp);
	id = 1, mx = 0;
	for (int r = 1; r <= n; r++) {
		while (b[id].s <= r && id <= m) mx = max(mx, b[id].i), id++;
		if (mx < r) ++anss, mx = r;
		else r = mx, ++anss;
	}
	if (type == 2) printf("%d\n", anss);
	else printf("%I64d %d\n", ansf + n, anss);
	return 0;	
}
posted @ 2019-10-29 10:00  Luckyblock  阅读(174)  评论(0编辑  收藏  举报