0
点赞
收藏
分享

微信扫一扫

CodeForces 1217E Sum Queries?(线段树)


CodeForces 1217E Sum Queries?(线段树)_CodeForces

CodeForces 1217E Sum Queries?(线段树)_线段树_02

 

 

打比赛的时候,最后两分钟发现是INF设小了,改了之后没来得及交上去比赛就结束了。。。

大致题意:有n个数字,m个操作。操作分为两种,1是修改某个数字,2是询问某个区间内是否存在一个集合,使得集合内数字的和存在至少一位,在所有的集合内数字对应位中都没有出现过,如果有输出最小的,否则输出-1。

看起来好难的样子,要求的是一个集合而不是连续区间,然后判断条件是和的每一位数字,而且要最小。其实最小是关键,经过观察样例和推理,我们可以发现,最后这个最小的和,一定是两个数字的和。因为,在任意一位上,两个非零的数字相加,其结果的数字一定不是原本的两个数字。也即,问题变成了,在一个区间内,按照位寻找,某一位不为0的最小和次小的两个数字。这个直接用线段树即可,对于每个位,只考虑当前位不为0的数字,维护区间最小和次小。

最后要注意,INF设置为2e9,因为是两个数字的和。具体见代码:

#include<bits/stdc++.h>
#define INF 2e9
#define eps 1e-6
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<" : "<<x<<endl
#define mem(x) memset(x,0,sizeof x)
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;

const int N = 200010;

int a[N],n,m;

struct ST
{
#define ls i<<1
#define rs i<<1|1

struct node
{
int min[10],mn[10],l,r;
} T[N<<2];

inline void push_up(int i)
{
for(int j=0;j<10;j++)
{
T[i].mn[j]=min(T[i<<1|1].mn[j],T[i<<1].mn[j]);
T[i].min[j]=min(T[i<<1|1].min[j],T[i<<1].min[j]);
T[i].mn[j]=min(max(T[i<<1|1].min[j],T[i<<1].min[j]),T[i].mn[j]);
}
}

void build(int i,int l,int r)
{
T[i].l=l; T[i].r=r;
for(int j=0;j<10;j++)
T[i].min[j]=T[i].mn[j]=INF;
if (l==r)
{
for(int x=a[l],t=0;x;x/=10,t++)
if (x%10) T[i].min[t]=a[l];
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
push_up(i);
}

void update(int i,int pos,int x)
{
if (T[i].l==T[i].r)
{
for(int j=0;j<10;j++)
T[i].min[j]=T[i].mn[j]=INF;
for(int y=x,t=0;y;y/=10,t++)
if (y%10) T[i].min[t]=x;
return;
}
int mid=(T[i].l+T[i].r)>>1;
if (mid>=pos) update(ls,pos,x);
else update(rs,pos,x);
push_up(i);
}

pair<int,int> getmin(int i,int l,int r,int id)
{
if ((T[i].l==l)&&(T[i].r==r)) return {T[i].min[id],T[i].mn[id]};
int mid=(T[i].l+T[i].r)>>1;
if (mid>=r) return getmin(ls,l,r,id);
else if (mid<l) return getmin(rs,l,r,id);
else
{
pair<int,int> a=getmin(ls,l,mid,id);
pair<int,int> b=getmin(rs,mid+1,r,id);
return {min(a.fi,b.fi),min(max(a.fi,b.fi),min(a.se,b.se))};
}
}

} seg;

int main()
{
scc(n,m);
for(int i=1;i<=n;i++) sc(a[i]);
seg.build(1,1,n);
while(m--)
{
int op,x,y;
sccc(op,x,y);
if (op==1) seg.update(1,x,y);
else
{
int ans=2e9;
for(int i=0;i<10;i++)
{
pair<int,int> tmp=seg.getmin(1,x,y,i);
if (tmp.fi!=INF&&tmp.se!=INF) ans=min(ans,tmp.fi+tmp.se);
}
if (ans==2e9) puts("-1"); else printf("%d\n",ans);
}
}
return 0;
}

 

举报

相关推荐

0 条评论