Selection Contest for Rookies 1 E Sum Queries?

任意两个数如果在某位上有重叠那么这两个数就可以取

最小值一定是在取区间内两个数的时候取到

按位拆分成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;
}

  

posted @ 2020-04-25 16:48  chinakevin  阅读(55)  评论(0编辑  收藏