zoukankan      html  css  js  c++  java
  • 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
    ", -1);
                else printf("%d
    ", ans);
            }
        }
        return 0;
    }
  • 相关阅读:
    【线程退出】linux线程退出的几个函数
    Apache Doris编译安装记录
    你所不知道的java编程思想
    thinking in java知识小记(一)
    一个程序员的修炼之路
    解决linux不能使用chmod更改权限的问题
    centos6.5配置无线网络
    ubuntu16.04 server安装小记
    vim的基本使用方法
    微信之父张小龙经典演讲164页PPT:《微信背后的产品观》
  • 原文地址:https://www.cnblogs.com/crraphael/p/11529579.html
Copyright © 2011-2022 走看看