CF1217E Sum Queries?
题意
我们这样定义一个多重集是平衡的:
对于sum
的每一个数位,多重集中至少有一个元素与sum
此数位相同
-
修改
a
数组中一个位置的值 -
询问一个区间中所有不平衡多重集的
sum
的最小值
思路
在一个数位若要达成平衡
- 一个数该位为
0-9
,其他数该位为0
- 产生进位,使出现相同
第二种方式是不可能的,若第i
位产生进位,则第i+1
位也必须产生进位,否则无法达成平衡
最高位也必然会进位,那么进位的那一位就无法达成平衡了
所以不平衡的情况即为该位上有两个非0
的数
对于每次询问,我们查询每个数为最小的两个非零数的和,即为最小集
查询最小的两个数,可以直接将节点定义为该区间最小的两个数
代码
#include <bits\stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 5;
const int inf = 2e9 + 5;
int a[maxn], b[maxn];
typedef pair<int, int> pii;
pii merge(const pii& a, const pii& b)
{
return a.first < b.first ? (a.second < b.first ? a : make_pair(a.first, b.first)) : (b.second < a.first ? b : make_pair(b.first, a.first));
}
struct Tree {
pii tree[maxn << 2];
void build(int root, int left, int right)
{
if (left == right) {
if (a[left] % 10 == 0)
tree[root] = make_pair(inf, inf);
else
tree[root] = make_pair(b[left], inf);
a[left] /= 10;
return;
}
int mid = (left + right) >> 1;
build(root << 1, left, mid);
build(root << 1 | 1, mid + 1, right);
tree[root] = merge(tree[root << 1], tree[root << 1 | 1]);
}
void update(int root, int left, int right, int x)
{
if (left == right) {
if (a[left] % 10 == 0)
tree[root] = make_pair(inf, inf);
else
tree[root] = make_pair(b[left], inf);
a[left] /= 10;
return;
}
int mid = (left + right) >> 1;
if (x <= mid)
update(root << 1, left, mid, x);
else
update(root << 1 | 1, mid + 1, right, x);
tree[root] = merge(tree[root << 1], tree[root << 1 | 1]);
}
pii query(int root, int left, int right, int stdl, int stdr)
{
if (left >= stdl && right <= stdr)
return tree[root];
int mid = (left + right) >> 1;
pii res = make_pair(inf, inf);
if (stdl <= mid)
res = merge(res, query(root << 1, left, mid, stdl, stdr));
if (stdr > mid)
res = merge(res, query(root << 1 | 1, mid + 1, right, stdl, stdr));
return res;
}
} T[9];
int main()
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = a[i];
}
for (int i = 0; i < 9; i++)
T[i].build(1, 1, n);
int opt, x, y;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &opt, &x, &y);
if (opt == 1) {
a[x] = b[x] = y;
for (int j = 0; j < 9; j++)
T[j].update(1, 1, n, x);
} else {
int ans = inf;
for (int j = 0; j < 9; j++) {
pii cnt = T[j].query(1, 1, n, x, y);
if (cnt.second == inf || cnt.first == inf)
continue;
ans = min(ans, cnt.first + cnt.second);
}
if (ans == inf)
printf("-1\n");
else
printf("%d\n", ans);
}
}
return 0;
}