Chef has an array A of size N. His friend Chuwi playing with this array in a next way: he chooses a continuous subarray A[L..R] and finds the maximum of (A[M] - A[L]) * (A[R] - A[M]) over all values of M where L ≤ M ≤ R. Chef wants to hopple Chuwi and changes elements of his array sometimes. Please help Chuwi to solve this easy problem.
Input
The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows. The first line of each test case contains two positive integers N denoting the number of elements in Chef's array and Q denoting the number of operations performed by Chef and Chuwi. The second line contains N space-separated integers A1, A2, ..., AN denoting the Chef's array. Next Q contains three integers - type = 1 L R denoting that Chuwi takes subarray A[L..R] and finds the maximum of his function. type = 2 X Y denoting that Chef changes element A[X] by Y.
Output
For every Chuwi's performed operation output the maximal value in a single line.
Constraints
- 1 ≤ T ≤ 1000
- 1 ≤ N, Q ≤ 105
- 1 ≤ Ai, Y ≤ 109
- 1 ≤ L ≤ R ≤ N
- 1 ≤ X ≤ N
- 1 ≤ type ≤ 2
- Sum of N over all test cases ≤ 2*105
- Sum of Q over all test cases ≤ 2*105
Subtasks
- Subtask #1: (20 points) sum of N over all test cases ≤ 5*103 and sum of Q over all test cases ≤ 5*103 and TL = 1 sec
- Subtask #2: (30 points) 1 ≤ Ai, Y ≤ 102
- Subtask #3: (50 points) Original constraints
Example
Input: 1 4 3 2 1 4 3 1 1 4 2 2 3 1 1 3 Output: 0 1
Explanation
Example case 1. For Chuwi's subarray [2, 1, 4, 3] there are 4 possible values of (A[M] - A[L]) * (A[R] - A[M]) - {0, -2, -2, 0} correspondingly, maximal value will be 0. After the second operation array will be [2, 3, 4, 3]. And for Chuwi's subarray [2, 3, 4] possible 3 values - {0, 1, 0}, hence answer is 1.
题意:大厨有一个长度为 N 的序列 A。他的朋友 Chuwi 在干这样的事情:选择一段连续的序列并A[L..R] 求出下式的最大值:(A[M] − A[L]) · (A[R] − A[M])其中 L ≤ M ≤ R。大厨想整一下 Chuwi,所以他会时不时地改变序列中一些元素的值。请帮Chuwi 搞定这道水题。思路:显然这是一个开口向下的二次函数,最值在X=(A[L]+A[R])/2处取得,那么我们在所给区间内找到距离它最近的点即可。那么线段树能不能使其线段内的数都有序呢?这样子就能二分查找了,用set就行,建树的时候合并区间set应该按顺序插入减少时间消耗,同时节点存数的2倍方便查找。
# include <iostream>
# include <cstdio>
# include <algorithm>
# include <set>
# define lson l,m,id<<1
# define rson m+1,r,id<<1|1
# define inf 0x7fffffff
using namespace std;
typedef long long LL;
const int maxn = 1e5+3;
multiset<int>s[4*maxn];
int a[maxn];
void build(int l, int r, int id)
{
s[id].clear();
if(l==r)
{
s[id].insert(a[l]<<1);
return;
}
int m = l+r>>1;
build(lson);
build(rson);
auto it1=s[id<<1].begin();
auto it2=s[id<<1|1].begin();
while(it1!=s[id<<1].end() && it2!=s[id<<1|1].end())
{
if(*it1 <= *it2)
{
s[id].insert(*it1);
++it1;
}
else
{
s[id].insert(*it2);
++it2;
}
}
for(;it1 != s[id<<1].end();++it1) s[id].insert(*it1);
for(;it2 != s[id<<1|1].end();++it2) s[id].insert(*it2);
}
int query(int L, int R, int num, int l, int r, int id)
{
if(L<=l &&R>=r)
{
int res = inf, ans;
auto it = s[id].upper_bound(num);
if(it != s[id].end())
if(abs(*it-num) < res) ans = *it, res=abs(*it-num);
if(it-- != s[id].begin())
if(abs(*it-num) < res) ans = *it;
return ans;
}
int m = l+r>>1, res=inf, ans;
if(L<=m)
{
int tmp = query(L, R, num, lson);
if(abs(tmp-num) < res) ans = tmp, res=abs(tmp-num);
}
if(R > m)
{
int tmp = query(L, R, num, rson);
if(abs(tmp-num) < res) ans = tmp;
}
return ans;
}
void update(int pos, int num, int pre, int l, int r, int id)
{
s[id].erase(s[id].find(pre<<1));
s[id].insert(num<<1);
if(l == r) return;
int m = l+r>>1;
if(pos<=m) update(pos, num, pre, lson);
if(pos > m) update(pos, num, pre, rson);
}
int main()
{
int T, n, q;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
build(1,n,1);
while(q--)
{
int op, l, r;
scanf("%d%d%d",&op,&l,&r);
if(op==1)
{
int big = a[l]+a[r];
int ans = query(l,r,big,1,n,1)/2;
printf("%lld\n",(1LL*ans-a[l])*(1LL*a[r]-ans));
}
else
{
update(l, r, a[l], 1, n, 1);
a[l] = r;
}
}
}
return 0;
}