题意:
当集合中有某两个元素的十进制表示在某一位均不为0,就认为这是一个不平衡的multiset。
现在给出一个数组,每次单点修改一个值,查询某个区间所有的数能组成的元素和最小的不平衡的multiset。
思路:
最小的multiset肯定是由两个数构成。由于十进制上的每一位都是相互独立的,那么就对每一位做一棵线段树,维护区间前两小即可,如果某个数字在某一位上是0,就记为inf,否则就记为该数本身。
参考代码:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
const int INF=2e9+5;
int a[N];
int tree[10][N<<2][2];
int ten[10]={
1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000
};
int cal(int x,int id){//某个数在某个数位上是0就返回inf
int tp=x/ten[id];
if(tp%10){
return x;
}
else{
return INF;
}
}
#define lson rt<<1
#define rson rt<<1|1
struct node{
int minn[2];
node(){
this->minn[0]=this->minn[1]=INF;
}
node(int a,int b){
this->minn[0]=a;
this->minn[1]=b;
}
};
node cal2(node a,node b){
node ret;
int sz=0;
for(int t1=0,t2=0;t1<=1&&t2<=1;){
if(sz==2)break;
if(a.minn[t1]<=b.minn[t2]){
ret.minn[sz++]=a.minn[t1];
t1++;
}
else{
ret.minn[sz++]=b.minn[t2];
t2++;
}
}
return ret;
}
void push_up(int id,int rt){
node a=node(tree[id][lson][0],tree[id][lson][1]);
node b=node(tree[id][rson][0],tree[id][rson][1]);
node c=cal2(a,b);
tree[id][rt][0]=c.minn[0];
tree[id][rt][1]=c.minn[1];
}
void build(int id,int rt,int l,int r){
if(l==r){
tree[id][rt][0]=cal(a[l],id);
tree[id][rt][1]=INF;
return;
}
int mid=(l+r)>>1;
build(id,lson,l,mid);
build(id,rson,mid+1,r);
push_up(id,rt);
}
void update(int id,int rt,int l,int r,int x,int v){
if(l==r){
tree[id][rt][0]=cal(v,id);
tree[id][rt][1]=INF;
return;
}
int mid=(l+r)>>1;
if(x<=mid)update(id,lson,l,mid,x,v);
else update(id,rson,mid+1,r,x,v);
push_up(id,rt);
}
node query(int id,int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
node ret;
ret.minn[0]=tree[id][rt][0];
ret.minn[1]=tree[id][rt][1];
return ret;
}
int mid=(l+r)>>1;
if(y<=mid)return query(id,lson,l,mid,x,y);
else if(x>mid)return query(id,rson,mid+1,r,x,y);
else return cal2(query(id,lson,l,mid,x,mid),query(id,rson,mid+1,r,mid+1,y));
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<10;i++){
build(i,1,1,n);
}
int op,x,y;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op,&x,&y);
if(op==1){
for(int j=0;j<10;j++){
update(j,1,1,n,x,y);
}
}
else{
int ans=INF;
for(int j=0;j<10;j++){
node tp=query(j,1,1,n,x,y);
// printf("%d %d\n",tp.minn[0],tp.minn[1]);
int tmp;
if(tp.minn[1]==INF){//第二小是inf说明只有一个数在该位置上不为0
tmp=INF;
}
else{
tmp=tp.minn[0]+tp.minn[1];
}
ans=min(ans,tmp);
}
printf("%d\n",ans==INF?-1:ans);
}
}
return 0;
}