对每个数位建棵线段树,每次取同一数位上不为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; }