任意两个数如果在某位上有重叠那么这两个数就可以取
最小值一定是在取区间内两个数的时候取到
按位拆分成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