任意两个数如果在某位上有重叠那么这两个数就可以取
最小值一定是在取区间内两个数的时候取到
按位拆分成10棵线段树,记录当前区间的最小值和次小值
不要忘记合并
时间复杂度O(10(n+m)logn)
#include<bits/stdc++.h> using namespace std; #define N 200005 #define inf 2000000005 int n, m, i, a[N], x, y, j, Divy, t, b[11][N<<2][2], ans; pair<int,int> anst; inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < ‘0‘ || ch > ‘9‘){ if(ch == ‘-‘) w = -1; ch = getchar();} while(ch >= ‘0‘ && ch <= ‘9‘) s = s * 10 + ch - ‘0‘, ch = getchar(); return s * w; } void up(int num,int x) { int ls=x<<1,rs=ls+1; if (b[num][ls][0]<b[num][rs][0]) { if (b[num][ls][1]<b[num][rs][0]) { b[num][x][0]=b[num][ls][0]; b[num][x][1]=b[num][ls][1]; } else { b[num][x][0]=b[num][ls][0]; b[num][x][1]=b[num][rs][0]; } } else { if (b[num][ls][0]<b[num][rs][1]) { b[num][x][0]=b[num][rs][0]; b[num][x][1]=b[num][ls][0]; } else { b[num][x][0]=b[num][rs][0]; b[num][x][1]=b[num][rs][1]; } } } void build(int num,int x,int l,int r) { if (l==r) { b[num][x][0]=b[num][x][1]=inf; return; } int mid=(l+r)>>1; build(num,x<<1,l,mid),build(num,x*2+1,mid+1,r); b[num][x][0]=b[num][x][1]=inf; } void insert(int num,int p,int l,int r,int x,int y) { if (l==r) { b[num][p][0]=y; b[num][p][1]=inf; return; } int mid=(l+r)>>1; if (x<=mid) insert(num,p<<1,l,mid,x,y); else insert(num,p<<1|1,mid+1,r,x,y); up(num,p); } pair<int,int> query(int num,int p,int l,int r,int L,int R) { if (L<=l&&r<=R) return make_pair(b[num][p][0],b[num][p][1]); int anst=0, ans[5]; pair<int,int> ls, rs; int mid=(l+r)>>1; if (L<=mid) { ls=query(num,p<<1,l,mid,L,R); ans[++anst]=ls.first; ans[++anst]=ls.second; } if (R>mid) { rs=query(num,p<<1|1,mid+1,r,L,R); ans[++anst]=rs.first; ans[++anst]=rs.second; } sort(ans+1,ans+anst+1); return make_pair(ans[1],ans[2]); } int main (void) { n=read(),m=read(); for (i=1; i<=n; i++) a[i]=read(); for (i=1; i<=10; i++) build(i,1,1,n); for (i=1; i<=n; i++) { x=a[i]; for (j=1; j<=10; j++) { if (x%10) insert(j,1,1,n,i,a[i]); else insert(j,1,1,n,i,inf); x/=10; } } for (; m; m--) { t=read(),x=read(),y=read(); if (t==1) { Divy=y; for (i=1; i<=10; i++) { if (Divy%10) insert(i,1,1,n,x,y); else insert(i,1,1,n,x,inf); Divy/=10; } } else { ans=inf; for (i=1; i<=10; i++) { anst=query(i,1,1,n,x,y); if (anst.first==inf||anst.second==inf) continue; ans=min(ans,anst.first+anst.second); } if (ans==inf) puts("-1"); else printf("%d\n",ans); } } return 0; }
Selection Contest for Rookies 1 E Sum Queries?
原文:https://www.cnblogs.com/chinakevin/p/12773841.html