考场思路,具体是每个点维护 lrm,意为记录区间的值是从左区间、右区间或是整个区间得来,以便于判断是否能将得到的两个值相乘
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=200005,MAXFLOW=1ll<<30;
int n,q,a[MAXN];
struct Tree{
int l,r,v,lrm;// lrm取值:0为取左区间,1为取右区间,2为左右合并(相乘),3为严格子区间
}t[MAXN<<2|1];
inline bool check(int l,int r){
return ((l==1||l==2)&&(r==0||r==2));
}
inline int getmax(int x,int y,int lx,int rx,int &lrm){
int ans;
if((!~x)||(!~y)){ // 特判Too large
ans=-1;
if((!~x)&&(!~y)) // 左右都Too large的话选哪边没区别,因为最终结果都是Too large
lrm=2;
else if(!~x){
if(lx==0||lx==2)
lrm=0;
else
lrm=3;
}else{
if(rx==1||rx==2)
lrm=1;
else
lrm=3;
}
return ans;
}
if(x>y){ // 正常处理
ans=x;
if(lx==0||lx==2)
lrm=0;
else
lrm=3;
}else{
ans=y,lrm=1;
}
if(x==y)
lrm=2;
if(check(lx,rx)) // 可以合并
if(x*y>ans){ // 没有1取不到等号
ans=x*y;
if(lx==2){
if(rx==2)
lrm=2;
else // rx==0
lrm=0;
}else if(rx==2)
lrm=1; // rx=lx=2的情况上面有了,此时一定lx=1
else
lrm=3;
}
if(ans>MAXFLOW)
ans=-1;
return ans;
}
inline void pushup(int x){
t[x].v=getmax(t[x<<1].v,t[x<<1|1].v,t[x<<1].lrm,t[x<<1|1].lrm,t[x].lrm);
}
void bt(int x,int l,int r){
t[x].l=l,t[x].r=r;
if(l==r){
t[x].v=a[l];
t[x].lrm=2;
return ;
}
int mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
pushup(x);
}
void upd(int x,int k,int w){
if(k<1||k>n)
return ;
if(t[x].l==t[x].r){
assert(t[x].l==k);
return (void)(t[x].v=w);
}
int mid=(t[x].l+t[x].r)>>1;
if(k<=mid)
upd(x<<1,k,w);
else
upd(x<<1|1,k,w);
pushup(x);
}
int query(int x,int l,int r,int &lrm){
if(l>r)
return 0;
if(l<=t[x].l&&t[x].r<=r){
// fprintf(stderr,"end at [%lld, %lld]\n",t[x].l,t[x].r);
lrm=2;
return t[x].v;
}
int mid=(t[x].l+t[x].r)>>1,tmp=0,ans=0,tl=-1,tr=-1;
if(l<=mid){ // 处理左区间
ans=query(x<<1,l,r,tl);
if(tl==0||tl==2) // 如果左区间的值从左部分上来或者整个上来
lrm=0; // 总体是从左边上来的
else // 反之亦然
lrm=3;
}
if(mid<r){ // 处理右区间
tmp=query(x<<1|1,l,r,tr);
if(!ans){ // 取不到左区间
ans=tmp;
if(tr==1||tr==2)
lrm=1;
else
lrm=3;
}else
ans=getmax(ans,tmp,tl,tr,lrm);
}
// fprintf(stderr,"[%lld, %lld] from (%lld, %lld) = ans: %lld, lrm: %lld\n",t[x].l,t[x].r,tl,tr,ans,lrm);
// cerr<<"at: "<<ans<<" "<<tmp<<'\n';
if(ans>MAXFLOW)
ans=-1;
return ans;
}
signed main(){
// freopen("T1ex2.in","r",stdin);
// freopen("T1ex2.ans","w",stdout);
cin.tie(nullptr)->sync_with_stdio(false);
cin>>n>>q;
for(int i=1;i<=n;i++)
cin>>a[i];
bt(1,1,n);
for(int i=1,op,x,y,lrm;i<=q;i++){
cin>>op>>x>>y;
if(op==1)
upd(1,x,y);
else{
int k=query(1,x,y,lrm);
if(!~k)
cout<<"Too large\n";
else
cout<<max(1ll,k)<<'\n';
}
}
return 0;
}