CF1217E Sum Queries

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qcwlmqy/article/details/102511618

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;
}

猜你喜欢

转载自blog.csdn.net/qcwlmqy/article/details/102511618