还是很有必要进行每日训练的,之前摆一摆倒还好,组队之后比赛量肯定会上去,再不练一练到时候只能天天拖队友后腿了(悲
这学期的学业压力也不小,尤其是我非常不擅长物理+实验,模电信号物光等等的课程对我来说是地狱级难度。只能看看每天能不能挤出来时间训练了。
每天最少会写一道题。
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;
}
标签:last,21,训练,int,ll,long,2023.2,ans,define
From: https://www.cnblogs.com/misasteria/p/17142882.html