每日训练-2023.2.21

还是很有必要进行每日训练的,之前摆一摆倒还好,组队之后比赛量肯定会上去,再不练一练到时候只能天天拖队友后腿了(悲
这学期的学业压力也不小,尤其是我非常不擅长物理+实验,模电信号物光等等的课程对我来说是地狱级难度。只能看看每天能不能挤出来时间训练了。
每天最少会写一道题。

acwing周赛91

A

直接模拟即可

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
using namespace std;
char s[100000];
int a[100010];
void solve() {
	int cnt = 0;
	scanf("%s", s + 1);
	for (int i = 1; i <= strlen(s + 1); i++) {
		int num = (s[i] - '0') * (int)pow(10, strlen(s + 1) - i);
		if (s[i] != '0') a[++cnt] = num;
	}
	printf("%d\n", cnt);
	for (int i = 1; i <= cnt; i++) printf("%d ", a[i]);
	printf("\n");
}
int main () {
	int t;
	scanf("%d", &t);
	while (t--) solve();
} 

B

显然只有端点才有可能死亡,直接枚举端点判断即可

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
using namespace std;
int a[200010] = {0};
int main () {
	int n, m;
	int last = 0, pos = 0;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d%d", &x, &y);
		if (pos && x != pos) {
			printf("%d %d", pos, a[pos]);
			return 0;
		}
		if (x > last + 1) {
			printf("%d 0", last + 1);
			return 0;
		}
		a[x]++;
		if (x != y) a[y]++;
		if (x == last) pos = last;
		last = y;
	}
	if (pos) {
		printf("%d %d", pos, a[pos]);
		return 0;
	}
	if (last != n) printf("%d 0", last + 1);
	else printf("OK");
	return 0;
} 

C

给定一个m行n列的整数矩阵,可以抽取其中的n-1行,构成一个新矩阵。在新矩阵中,存在一个最大的整数L,使得新矩阵的每一列中都存在至少一个数大于等于L。
好像是cf上的题,生动地体现出我没打cf(
手写了几组案例之后,可以看出一些规律。首先我们找出原矩阵每一列的最大值的min,记为minn, 比这个数更大的显然不符合要求。
然后对于一个备选答案x来说,因为 \(x\leq minn\), 说明每一列都至少有一个数大于等于x,那么如果有一行有大于等于两个数大于x,那么总的使用行数一定是小于等于n-1的。
于是我们找出每一行的第二大的数的最大值,和minn取min即可。

#include<bits/stdc++.h>
#define ll long long 
#define ull unsigned long long
using namespace std;
char s[10];
void solve() {
	cin.getline(s, 10);
	int m, n;
	scanf("%d%d", &m, &n);
	vector<int> maxn(n + 10, 0), max1(m + 10, 0), max2(m + 10, 0); 
	vector<vector<int> >a(m + 10, vector<int>(n + 10)); 
	for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			scanf("%d", &a[i][j]);
			if (a[i][j] >= max1[i]) max2[i] = max1[i], max1[i] = a[i][j];
			else if (a[i][j] >= max2[i]) max2[i] = a[i][j];
			maxn[j] = max(maxn[j], a[i][j]);
		}
	}
	/*for (int i = 1; i <= m; i++) {
		for (int j = 1; j <= n; j++) {
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}*/
	int minn = 1000000001, ans = 0;
	for (int i = 1; i <= m; i++) ans = max(ans, max2[i]);
	for (int i = 1; i <= n; i++) minn = min(minn, maxn[i]);
	//printf("%d %d\n ******* \n", minn, ans);
	printf("%d\n", min(ans, minn));
	
}
int main () {
	int t;
	scanf("%d", &t);
	while (t--) solve();
	return 0;
} 

牛客挑战赛108

A

一开始读假了题,把或看成了异或,想了一个线性基维护最大异或值 * 4的假方法。
正解比较显然,因为或不减,因此直接四个元素或起来 * 4就行了。
所以如果是异或的话应该怎么写(

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
void solve() {
	ll a, b, c, d;
	scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
    ll ans = 0;
    ans = ans | a, ans = ans | b, ans = ans | c, ans = ans | d;
	printf("%lld\n", 4 * ans);
}
int main () {
	int t;
	scanf("%d", &t);
	while (t--) solve();
}

B

因为 \(\sum n\) 为 2e5, 直接从左往右过一遍就行。

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
ll a[200005], b[200005], d[200005];
void solve() {
	int n, f = 1;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);
	for (int i = 1; i <= n; i++) {
		if (abs(a[i] - b[i]) % 2) f = 0;
		d[i] = (a[i] - b[i]) / 2;
	}
	if (!f) {
		puts("-1");
		return;
	}
    //for (int i = 1; i <= n; i++) cout << d[i] << " ";
   // cout << endl;
	ll ans = 0;
	for (int i = 1; i < n; i++) {
		d[i + 1] += d[i], ans += abs(d[i]);
	}
    if (d[n] != 0) {
        puts("-1");
        return;
    }
	printf("%lld\n", ans);
}
int main () {
	int t;
	scanf("%d", &t);
	while (t--) solve();
}

C

类似于权值树状数组的思想,令 \(c_i\) 为数组中 \(i\) 的个数,\(f_i\) 为c的前缀和 , \(f_i = \sum_{j=1}^ic_j\)
转化一下条件: \(a_i+a_j\leq w\)
\(a_j \leq w-a_i\)
固定 \(a_j\), 数量为 \(f_{w-i}\)
总数量为 \(\sum_{i=0}^wc_if_{w-i}\)
修改时可以单点修改完再query,或者分析一下性质直接修改ans也可。
由于后面的操作都是单点修改,在读入时按顺序query的,因此也满足 \(i\leq j\) 的条件

#include <bits/stdc++.h>
#define int long long
#define lowbit(x) (x) & (-x)
#define ull unsigned long long
using namespace std;
inline int read() {
	int x = 0, f = 1;
	char c = getchar();
	while (c > '9' || c < '0') {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}
const int N = 3e5 + 10;
int a[N], c[N];
int n, q, w, ans;
void add(int pos, int x) {
	for (int i = pos; i <= w + 1; i += lowbit(i)) c[i] += x;
}
int query(int pos) {
	int res = 0;
	for (int i = pos; i; i -= lowbit(i)) res += c[i];
	return res;
}
signed main () {
	n = read(), q = read(), w = read();
	for (int i = 1; i <= n; i++) a[i] = read(), add(a[i] + 1, 1), ans += query(w - a[i] + 1);
	while (q--) {
		int p = read(), x = read();
		ans -= query(w - a[p] + 1);
		add(a[p] + 1, -1), add(x + 1, 1), a[p] = x;
		ans += query(w - x + 1);
		printf("%lld\n", ans); 
	}
	return 0;
}
posted @ 2023-02-22 00:00  misasteria  阅读(38)  评论(0编辑  收藏  举报