19级暑假第二场训练赛

A题 CodeForces - 1234A

Example

Input

3
5
1 2 3 4 5
3
1 2 2cpp
4
1 1 1 1

Output

3
2
1

想复杂了,直接计算平均值向上取整

#include
using namespace std;
const int N = 110;
int a[N], t, n;
int main() {
	//freopen("in.txt", "r", stdin);
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> t; while (t--) {
		int sum = 0;
		cin >> n;
		for (int i = 1; i <= n; ++i)cin >> a[i], sum += a[i];
		int p = sum / n * n >= sum ? sum / n : sum / n + 1;
		cout << p << endl;
	}
}

B题 CodeForces - 1234B2

Examples

Input

7 2
1 2 3 2 1 3 2

Output

2
2 1 

Input

10 4
2 3 3 1 1 2 1 2 3 3

Output

3
1 3 2 

B题和C题是一样的只需要考虑数据规模即可

C题数据范围 \(1 <= d_i <= 10^9\)

思路:

根据题意,用队列模拟下,set存储目前显示的消息内容

#include 
using namespace std;
typedef long long ll;
deque  q;
set  s;
int main() {
	//freopen("in.txt", "r", stdin);
        int n, k;
	cin >> n >> k;
	for (int i = 1, x; i <= n; i++) {
		cin >> x;
		if (s.find(x) != s.end()) continue;//如果存在就跳过
		s.insert(x);
		q.push_front(x);
		if (q.size() > k) {
			s.erase(q.back());
			q.pop_back();
		}
	}
	cout << q.size() << '\n';
	for (auto x : q)
		cout << x << ' ';
}

D题:

CodeForces - 1234C

写的时候考虑不完全,这道题,我们可以把序号1、2的看成是一样的,再把序号3、4、5、6看成是一样的,所以在这里我看成了1号整体与2号整体。

然后,其实我们不难发现,路径是唯一的,也就是说我们的走法是唯一的,我们只需要判断下一步是不是还可以走就可以了。还有到达终点的过程。

AC代码

#include
using namespace std;
const int maxN = 2e5 + 7;
int N, dir[3][maxN];
char op[3][maxN];
inline bool dfs(int x, int y, int las_op, int lx, int ly){
    if (x == N + 1 && y == 1) return true;
    if (x > N || y > 2 || y < 1) return false;
    if (dir[y][x] == 1){
        if (lx == x) return false;
        return dfs(x + 1, y, 1, x, y);
    }
    else {
        if (lx == x) return dfs(x + 1, y, 2, x, y);
        else return dfs(x, 3 - y, 2, x, y);
    }
}
int main(){
    freopen("in.txt", "r", stdin);
    int T; scanf("%d", &T);
    while (T--) {
        scanf("%d", &N);
        for (int i = 2; i >= 1; i--) scanf("%s", op[i] + 1);
        for (int i = 1; i <= 2; i++) {
            for (int j = 1; j <= N; j++){
                if (op[i][j] <= '2') dir[i][j] = 1;
                else dir[i][j] = 2;
            }
        }
        bool flag;
        if (dir[2][1] == 1) flag = dfs(2, 2, 1, 1, 2);
        else flag = dfs(1, 1, 2, 1, 2);
        printf(flag ? "YES\n" : "NO\n");
    }
    return 0;
}

E题:

CodeForces - 1234D

19级暑假第二场训练赛_第1张图片

线段树、set容器

最先做的时候使用set容器但没剪枝,直接在大数据TLE,改用26个字母的线段树才过

#include 
using namespace std;
const int maxn = 1e5 + 100;
char str[maxn];
struct node {
	int l, r, sum;
}tr[26][maxn << 2];

void build(int root, int l, int r) {
	for (int i = 0; i < 26; i++) {
		tr[i][root].l = l; tr[i][root].r = r; tr[i][root].sum = 0;
	}
	if (l == r)//重合返回即可
		return;
	int mid = (l + r) >> 1;
	build(root << 1, l, mid);
	build(root << 1 | 1, mid + 1, r);
}

void update(int root, int trnum, int pos, int num) {
	if (tr[trnum][root].l == tr[trnum][root].r) {
		tr[trnum][root].sum += num;
		return;
	}
	int mid = (tr[trnum][root].l + tr[trnum][root].r) >> 1;
	if (pos <= mid) {
		update(root << 1, trnum, pos, num);
	}
	else {
		update(root << 1 | 1, trnum, pos, num);
	}
	tr[trnum][root].sum = tr[trnum][root << 1].sum + tr[trnum][root << 1 | 1].sum;
}

int query(int root, int trnum, int L, int R) {
	if (tr[trnum][root].l == L && tr[trnum][root].r == R)
		return tr[trnum][root].sum;
	int mid = (tr[trnum][root].l + tr[trnum][root].r) >> 1;
	if (R <= mid)
		return query(root << 1, trnum, L, R);
	else if (L > mid)
		return query(root << 1 | 1, trnum, L, R);
	else
		return query(root << 1, trnum, L, mid) + query(root << 1 | 1, trnum, mid + 1, R);

}

int main() {
	//freopen("in.txt", "r", stdin);
	int n, m, opt, x, y;
	char ss[5]; str[0] = '#';
	scanf("%s", &str[1]);
	n = strlen(str) - 1;
	build(1, 1, n);
	cin >> m;
	for (int i = 1; i <= n; i++) {
		update(1, str[i] - 'a', i, 1);
	}
	while (m--) {
		cin >> opt;
		if (opt == 1) {
			cin >> x >> ss;
			if (str[x] != ss[0]) {
				update(1, str[x] - 'a', x, -1);
				update(1, ss[0] - 'a', x, 1);
				str[x] = ss[0];
			}
		}
		else {
			cin >> x >> y;
			int c = 0;
			for (int i = 0; i < 26; i++) {
				if (query(1, i, x, y)) {
					c++;
				}
			}
			printf("%d\n", c);
		}
	}
}

贴一下dalao的set容器写法,作为学习

思路:这里用到了一个比较巧妙的技巧,用26个set来存储每个字母在字符串中出现的位置,因为STL中set是排序的,所以每次查询时,只需要遍历26个字母,查询其在字符串中第一次出现的在l之后的位置,若该位置比r要小,说明这个字符存在于这个区间之内,答案加1。更新时只需要在原串位置的字符对应的set中去除这个位置,并在新替换的字符对应的set中存入该位置即可。

#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5+10;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
char s[maxn];
int q;
set Set[26];
int main()
{
	scanf("%s", s+1);
	cin >> q;
	int n = strlen(s+1);
	for (int i = 1; i <= n; i++) 
		Set[s[i]-'a'].insert(i);
	for (int i = 0; i < q; i++) {
		int op;
		cin >> op;
		if (op == 1) {
			int p; char c;
			scanf("%d %c", &p, &c);
			int cur = s[p]-'a';
			if (Set[cur].count(p))
				Set[cur].erase(Set[cur].find(p));
			s[p] = c;
			Set[c-'a'].insert(p);
		} else {
			int l, r, ans = 0;
			scanf("%d%d", &l, &r);
			for (int j = 0; j < 26; j++) {
				int cur = *Set[j].lower_bound(l);
				if (cur >= l && cur <= r) {
					ans++;
				}
			}
			cout << ans << "\n";
		}
	}
	return 0;
}

你可能感兴趣的:(19级暑假第二场训练赛)