题意:长度为n的数列a,Q次操作.
操作1:给出(pos,x) 令a[pos]=x
操作2:给出[L,R] 问(a[L],a[L+1]..a[R]) 能组成的三角形中周长最长的为多少?
n,Q<=1e5,a[i]<=1e9.
先来一个暴力的解法:
对每个询问,枚举当前区间[l,r]第i个数作为最大值时,
因为三角形两边之和要大于第三边,所以剩下两个边在小于a[i]的情况下,显然越大越好.
对当前区间排个序 枚举一下即可 O(Q*nlogn)
对于询问的一个区间,因为周长要最长,所以按最大值从大到小的枚举最长边.
若有解,则立即退出.
否则,说明a[i]>=a[i+1]+a[i+2] 若一直无法组成三角形 则a[i]将以斐波那契数列的增长速度递减下去.
因为1<=a[i]<=1e9 枚举最大值的次数最多为k=50次.
要实现单点更新和区间第k大值的查询.若用权值线段树,a[i]较大还要在离散化一下.
因为要一个节点的前K大 这个信息显然可以合并
操作1:给出(pos,x) 令a[pos]=x
操作2:给出[L,R] 问(a[L],a[L+1]..a[R]) 能组成的三角形中周长最长的为多少?
n,Q<=1e5,a[i]<=1e9.
先来一个暴力的解法:
对每个询问,枚举当前区间[l,r]第i个数作为最大值时,
因为三角形两边之和要大于第三边,所以剩下两个边在小于a[i]的情况下,显然越大越好.
对当前区间排个序 枚举一下即可 O(Q*nlogn)
对于询问的一个区间,因为周长要最长,所以按最大值从大到小的枚举最长边.
若有解,则立即退出.
否则,说明a[i]>=a[i+1]+a[i+2] 若一直无法组成三角形 则a[i]将以斐波那契数列的增长速度递减下去.
因为1<=a[i]<=1e9 枚举最大值的次数最多为k=50次.
要实现单点更新和区间第k大值的查询.若用权值线段树,a[i]较大还要在离散化一下.
因为要一个节点的前K大 这个信息显然可以合并
每个节点合并花费时间为K,每次查询和更新最多logn次合并.直接用线段树搞搞即可.O(Q*K*logn)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,K=51;
int n;
ll a[N];
struct node{
vector<ll> v;
int l,r;
}t[N<<2];
vector<ll> Merge(vector<ll> a,vector<ll> b)
{
vector<ll> c;
int i=0,j=0;
while(i<a.size()&&j<b.size()&&c.size()<K)
{
if(a[i]>=b[j])
c.push_back(a[i]),i++;
else
c.push_back(b[j]),j++;
}
if(c.size()<K)
{
while(i<a.size()&&c.size()<K)
c.push_back(a[i]),i++;
while(j<b.size()&&c.size()<K)
c.push_back(b[j]),j++;
}
return c;
}
void push_up(int o)
{
t[o].v=Merge(t[o<<1].v,t[o<<1|1].v);
}
void build(int o,int l,int r)
{
t[o].l=l,t[o].r=r;
if(l==r)
{
t[o].v.push_back(a[l]);
return;
}
int mid=l+r>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
push_up(o);
}
void update(int o,int pos,ll val)
{
int l=t[o].l,r=t[o].r,mid=l+r>>1;
if(l==r)
{
t[o].v.clear();
t[o].v.push_back(val);
return;
}
if(pos<=mid)
update(o<<1,pos,val);
else
update(o<<1|1,pos,val);
push_up(o);
}
vector<ll> query(int o,int ql,int qr)
{
vector<ll> res;
int l=t[o].l,r=t[o].r;
if(l>=ql&&r<=qr)
return t[o].v;
int mid=l+r>>1;
if(ql<=mid)
res=Merge(res,query(o<<1,ql,qr));
if(qr>mid)
res=Merge(res,query(o<<1|1,ql,qr));
return res;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
int Q,op;
ll l,r,x;
cin>>n>>Q;
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,1,n);
while(Q--)
{
cin>>op>>l>>r;
if(op==1)
update(1,l,r);
else
{
ll ans=0;
vector<ll> res=query(1,l,r);
for(int i=0;i+2<res.size();i++)
{
ll x=res[i],y=res[i+1],z=res[i+2];
if(y+z>x)
{
ans=x+y+z;
break;
}
}
cout<<ans<<'\n';
}
}
return 0;
}