CF1217E Sum Queries? 题解

对每个数位建棵线段树,每次取同一数位上不为0的数中最小的2个。

没了?

没了。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define p2 pair<int, int> 
using namespace std;

const int maxn = 1000005;
const int inf = 0x3f3f3f3f;
int n, m;
int ans1, ans2, ans;

struct atree {
    int min1[maxn], min2[maxn];
    void cle() {
        memset(min1, 0x3f, sizeof(min1));
        memset(min2, 0x3f, sizeof(min2));
    }
    void change(int x, int l, int r, int p, int num) {
        //cout<<l<<' '<<r<<endl;
        if(l == r) {
            min1[x]=num; min2[x]=inf; return;
        }
        int mid=(l+r)/2;
        if(p <= mid) change(x*2, l, mid, p, num);
        else change(x*2+1, mid+1, r, p, num);
        min2[x]=min(min(min2[x*2], min2[x*2+1]), max(min1[x*2], min1[x*2+1]));
        min1[x]=min(min1[x*2], min1[x*2+1]);
        return;
    }
    void count(int x, int l, int r, int pl, int pr) {
        if(r < pl || pr < l) return;
        if(pl <= l && r <= pr) {
        //cout<<' '<<l<<' '<<r<<' '<<min1[x]<<' '<<min2[x]<<endl;
            ans2=min(min(min2[x], ans2), max(min1[x], ans1));
            ans1=min(min1[x], ans1);
            return;
        }
        int mid=(l+r)/2;
        count(x*2, l, mid, pl, pr);
        count(x*2+1, mid+1, r, pl, pr);
        return;
    }
} T[15];

int main() {
    int i, j, b, ta, tb, tp;
    for(i=1; i <= 10; i++) T[i].cle();
    scanf("%d%d", &n, &m);
    for(i=1; i <= n; i++) {
        scanf("%d", &ta);
        tb=ta; j=0;
        while(tb != 0) {
            j++;
            if(tb % 10 != 0) T[j].change(1, 1, n, i, ta);
            tb/=10;
        }
    }
    for(i=n+1; i <= n+m; i++) {
        scanf("%d%d%d", &b, &ta, &tb);
        if(b == 1) {
            tp=ta; ta=tb;
            for(j=1; j <= 10; j++) {
                T[j].change(1, 1, n, tp, inf);
            }
            j=0;
            while(tb != 0) {
                j++;
                if(tb % 10 != 0) T[j].change(1, 1, n, tp, ta);
                tb/=10;
            }
        }
        else {
            ans=inf*2;
            for(j=1; j <= 10; j++) {
                ans2=ans1=inf;
                T[j].count(1, 1, n, ta, tb);
                if(ans1 != inf && ans2 != inf && ans > ans1+ans2) ans=ans1+ans2;
            }
            if(ans == inf*2) printf("%d\n", -1);
            else printf("%d\n", ans);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/crraphael/p/11529579.html