A-gzm批试卷
Tag 线段树
#include <iostream>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N = 2e5 + 2;
int n, m, a[N];
ll tree[N << 2], mark[N << 2];
inline void build(int p = 1, int cl = 1, int cr = n) {
if (cl == cr) {
tree[p] = a[cl];
return;
}
int mid = cl + cr >> 1;
build(p << 1, cl, mid);
build(p << 1 | 1, mid + 1, cr);
tree[p] = max(tree[p << 1 | 1], tree[p << 1]);
}
inline void push_down(int p, int len) {
if (!mark[p] || len == 1) return;
mark[p << 1] = max(mark[p], mark[p << 1]);
mark[p << 1 | 1] = max(mark[p], mark[p << 1 | 1]);
tree[p << 1] = max(mark[p], tree[p << 1]);
tree[p << 1 | 1] += max(mark[p], tree[p << 1 | 1]);
mark[p] = 0;
}
inline ll query(int l, int r, int p = 1, int cl = 1, int cr = n) {
if (l <= cl && cr <= r) return tree[p];
push_down(p, cr - cl + 1);
ll ans = 0;
int mid = cl + cr >> 1;
if (mid >= l) ans = max(ans, query(l, r, p << 1, cl, mid));
if (mid < r) ans = max(ans, query(l, r, p << 1 | 1, mid + 1, cr));
return ans;
}
inline void update(int l, int r, ll k, int p = 1, int cl = 1, int cr = n) {
if (cl == cr) {
tree[p] = k;
return;
}
if (l <= cl && cr <= r) {
tree[p] = max(k, tree[p]);
mark[p] = max(mark[p], k);
return;
}
push_down(p, cr - cl + 1);
int mid = cl + cr >> 1;
if (mid >= l) update(l, r, k, p << 1, cl, mid);
if (mid < r) update(l, r, k, p << 1 | 1, mid + 1, cr);
tree[p] = max(tree[p << 1], tree[p << 1 | 1]);
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
build();
while (m --) {
char op; int l, r; scanf(" %c%d%d", &op, &l, &r);
if (op == 'Q') cout << query(l, r) << endl;
else update(l, l, r);
}
return 0;
}
B-gzm的新栈
Tag stack
#include <iostream>
#define endl '\n'
using namespace std;
const int N = 1e5 + 2;
int tree[N], a[N], stk[N], tt;
inline int lowbit(int x) {
return x & -x;
}
inline int query(int x) {
int res = 0;
while (x) {
res += tree[x];
x -= lowbit(x);
}
return res;
}
inline void update(int x, int k) {
int n = tt;
while (x < N) {
tree[x] += k;
x += lowbit(x);
}
}
int main() {
cin.tie(nullptr);
int m; cin >> m;
while (m --) {
string op; cin >> op;
if (op == "Pop") {
if (!tt) {
puts("Invalid");
continue;
}
cout << a[tt] << endl;
update(a[tt], -1);
tt --;
} else if (op == "Push") {
tt ++;
cin >> a[tt];
update(a[tt], 1);
} else {
if (!tt) {
puts("Invalid");
continue;
}
int n = tt;
int l = 1, r = N;
while (l < r) {
int mid = l + r >> 1;
if (query(mid) >= (n + 2) / 3) r = mid;
else l = mid + 1;
}
cout << l << endl;
}
}
return 0;
}
C-gzm的可变数组
题意 并查集
#include <iostream>
using namespace std;
const int N = 2e5 + 2;
int n, q, a[N], p[N];
void convert(int x) {
int res = 0;
while (a[x]) {
res += a[x] % 10;
a[x] /= 10;
}
a[x] = res;
}
int find(int x) {
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main() {
int T; cin >> T;
while (T --) {
cin >> n >> q;
p[n + 1] = n + 1;
for (int i = 1; i <= n; i ++) cin >> a[i], p[i] = i;
while (q --) {
int op; cin >> op;
if (op == 1) {
int l, r; cin >> l >> r;
while (l <= r) {
convert(l);
if (a[l] < 10) p[l] = l + 1;
l ++;
l = find(l);
}
} else {
int x; cin >> x;
cout << a[x] << '\n';
}
}
}
return 0;
}
D-gzm的旋转图腾
#include <iostream>
#define read(x) scanf("%d", &x)
using namespace std;
typedef long long ll;
const int N = 1e3 + 2;
int n, k;
int a[N][N];
int main() {
int T; read(T);
while (T --) {
read(n), read(k);
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++)
read(a[i][j]);
int res = 0;
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++)
if (a[i][j] != a[n - i - 1][n - j - 1]) res ++;
res /= 2;
if (res <= k && (n & 1 || (k - res) % 2 == 0))
puts("YES");
else puts("NO");
}
return 0;
}
E-gzm学线段树
题意 线段树
#include <iostream>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N = 1e5 + 2;
int n, m, a[N];
ll tree[N << 2], mark[N << 2];
inline void build(int p = 1, int cl = 1, int cr = n) {
if (cl == cr) {
tree[p] = a[cl];
return;
}
int mid = cl + cr >> 1;
build(p << 1, cl, mid);
build(p << 1 | 1, mid + 1, cr);
tree[p] = tree[p << 1 | 1] + tree[p << 1];
}
inline void push_down(int p, int len) {
if (!mark[p] || len == 1) return;
mark[p << 1] += mark[p];
mark[p << 1 | 1] += mark[p];
tree[p << 1] += mark[p] * (len - len / 2);
tree[p << 1 | 1] += mark[p] * (len / 2);
mark[p] = 0;
}
inline ll query(int l, int r, int p = 1, int cl = 1, int cr = n) {
if (l <= cl && cr <= r) return tree[p];
push_down(p, cr - cl + 1);
ll ans = 0;
int mid = cl + cr >> 1;
if (mid >= l) ans += query(l, r, p << 1, cl, mid);
if (mid < r) ans += query(l, r, p << 1 | 1, mid + 1, cr);
return ans;
}
inline void update(int l, int r, ll k, int p = 1, int cl = 1, int cr = n) {
if (l <= cl && cr <= r) {
tree[p] += (cr - cl + 1) * k;
mark[p] += k;
return;
}
push_down(p, cr - cl + 1);
int mid = cl + cr >> 1;
if (mid >= l) update(l, r, k, p << 1, cl, mid);
if (mid < r) update(l, r, k, p << 1 | 1, mid + 1, cr);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++) scanf("%d", &a[i]);
build();
while (m --) {
char op; int l, r; scanf(" %c%d%d", &op, &l, &r);
if (op == 'Q') {
cout << query(l, r) << endl;
} else {
ll k; scanf("%lld", &k);
update(l, r, k);
}
}
return 0;
}
F-gzm的新启发式可持久化线段树维护多重背包
题解 从后往前遍历如果是负数先删除,随后始终删除第一个数直至删完
#include <iostream>
using namespace std;
typedef long long ll;
int n, m;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
ll res = 0;
for (int i = 1; i <= n; i ++) {
ll x; cin >> x;
if (x >= 0) res += x;
if (x < 0) res += x * i;
}
cout << res << endl;
return 0;
}