Thank you for participation and we hope you enjoy this round :)
Additionally, we sincerely invite you to join the unofficial round of TheForces Community tomorrow. Compete alongside many high-rated participants and earn your own rating in a our own rating system(TheForces Rating System)!
For more details, pls read https://codeforces.me/blog/entry/131733.
A — Submission Bait
For Alice, what if choosing the maximum value doesn't work?
Consider parity.
Case $$$1$$$: When all values appear an even number of times, Alice will lose. This is because no matter which number Alice chooses, Bob can mimic Alice's move.
Case $$$2$$$: When at least one value appears an odd number of times, Alice will win. Alice only needs to choose the maximum value that appears an odd number of times, which will force Bob into Case $$$1$$$.
Time complexity: $$$O(n)$$$.
Sort the array $$$a$$$ in non-increasing order. We can observe that any state can be represented as a prefix of the array $$$a$$$. Consider dynamic programming: let $$$dp_i$$$ denote whether the first player is guaranteed to win when the state is $$$a_{1...i}$$$ ($$$dp_i=1$$$ indicates a guaranteed win for the first player). We have the following formula:
$$$dp_1=1$$$;
$$$dp_i= \sim (dp_{i-1}$$$ & $$$dp_{id_1-1}$$$ & $$$dp_{id_2-1} \ldots)$$$, where $$$id_j$$$ satisfies $$$a_{id_j} \neq a_{id_j+1}$$$ and $$$id_j < i$$$.
Time complexity: $$$O(n^2)$$$.
#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 55;
int n;
int q[N];
void solv()
{
cin >> n;
for (int i = 1; i <= n; ++i)
q[i] = 0;
for (int i = 1; i <= n; ++i)
{
int x;
cin >> x;
++q[x];
}
for (int i = 1; i <= n; ++i)
{
if (q[i] % 2 == 1)
{
cout << "YES\n";
return;
}
}
cout << "NO\n";
}
int main()
{
#ifdef SOMETHING
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif // SOMETHING
ios_base::sync_with_stdio(false), cin.tie(0);
int tt = 1;
cin >> tt;
while (tt--)
{
solv();
}
return 0;
}
B — Array Craft
Starting from a trival construction.
Adjust it.
First, we consider making $$$presum_x > presum_j$$$ for all $$$x < i \le n$$$, and similarly for $$$y$$$. We can think of a trivial construction: $$$a[r, \ldots ,l]=[1, \ldots ,1], a[1, \ldots...,r-1]=[-1, \ldots, -1]$$$ and $$$a[l+1,\ldots,n]=[-1, \ldots, -1]$$$.
The construction doesn't works when $$$presum_x<0$$$, but we are close to the correct solution. Next, we will make a little adjustment: $$$a[r, \ldots, l]=[1,\ldots,1], a[1, \ldots...,r-1]=[\ldots,1, -1]$$$ and $$$a[l+1,\ldots,n]=[-1,1, \ldots]$$$.
It is not hard to see $$$presum_x \ge presum_j$$$ for all $$$x < i \le n$$$, and for $$$1 \le i \le y$$$, $$$\max(presum_i)-min(presum_i)\le 1$$$. Thus, we get $$$presum_x \ge 2+presum_{y-1} \ge 2+min(presum_i) \ge 1+max(presum_i)$$$. The same applies to the suffix sum as well. Therefore, this construction is valid.
Time complexity: $$$O(n)$$$.
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while(t>0){
t--;
int n,x,y;
cin >> n >> x >> y;
x--; y--;
vector<int> a(n,1);
int e;
e=-1;
for(int i=x+1;i<n;i++){
a[i]=e;
e*=-1;
}
e=-1;
for(int i=y-1;i>=0;i--){
a[i]=e;
e*=-1;
}
for(int i=0;i<n;i++){
if(i){cout << " ";}
cout << a[i];
}cout << "\n";
}
return 0;
}
C — Mad MAD Sum
After one operation, the array becomes non-decreasing.
Consider $$$a_1=a_2=\ldots=a_n$$$, the operation seems to have shifted the array right.
When does the "right shift" parttern happen?
Read hints first.
Let's consider only non-decreasing arrays. Observe a continuous segments $$$a[l...r]=x(l<r,x>0)$$$, after one operation, we get $$$a[l+1,min(r+1,n)]=x$$$ holds. We can conclude that if, for all non-zero contiguous segments in the array (except the last one), their lengths are all greater than $$$1$$$, then the array follows the "right shift" parttern. Let's say this kind of array "good".
The last problem is when will the array become "good". Let's assume we get the array $$$b$$$ after one operation on array $$$a$$$, we get $$$b_i<b_{i+1}<b_{i+2}$$$. We can infer that $$$b_i=a_i,b_{i+1}=a_{i+1}$$$ and there is at least $$$a_j=a_{i+1}(j \le i)$$$, which shows that $$$a$$$ is not non-decreasing. In other words, after two operations, we can always get a "good" array. Then the calculating is trival.
Time complexity: $$$O(n)$$$.
#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 200005;
int n;
int a[N];
bool c[N];
void doit()
{
for (int i = 1; i <= n; ++i)
c[i] = false;
int maxu = 0;
for (int i = 1; i <= n; ++i)
{
if (c[a[i]])
maxu = max(maxu, a[i]);
c[a[i]] = true;
a[i] = maxu;
}
}
void solv()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
ll ans = 0;
for (int i = 1; i <= n; ++i)
ans += a[i];
doit();
for (int i = 1; i <= n; ++i)
ans += a[i];
doit();
for (int i = 1; i <= n; ++i)
ans += (n - i + 1) * 1LL * a[i];
cout << ans << "\n";
}
int main()
{
#ifdef SOMETHING
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif // SOMETHING
ios_base::sync_with_stdio(false), cin.tie(0);
int tt = 1;
cin >> tt;
while (tt--)
{
solv();
}
return 0;
}
The title "Mad MAD Sum" is not only a pun on the words Mad and MAD (Maximum Appearing Duplicate), but also implies the solution to the problem :)
D Grid Puzzle
Obviously, when $$$a_i$$$ is large enough, we will definitely use operation $$$2$$$ on the $$$i$$$-th line. What is its specific value?
It is $$$5$$$(try to prove it). Now we can only consider $$$a_i \le 4$$$ cases.
From left to right, consider a greedy solution or a DP solution.
We observe that, in fact, only the $$$>$$$ to the left of $$$p$$$ and the $$$<$$$ to the right of $$$p$$$ change the direction of the pinball placed at position $$$p$$$ initially.
For convenience, let's assume $$$s_p$$$ is $$$>$$$, $$$k=min(countright(1,p),countleft(p+1,n))$$$, and the pinball leaves from the left boundary(for other situations, we can handle them in a similar way).
We can obtain $$$right[1,\ldots,k]$$$ and $$$left[1,\ldots,k]$$$ through prefix sum + binary search, where $$$right$$$ represents the indices of $$$>$$$ to the left of $$$p$$$ (in decreasing order), and $$$left$$$ represents the indices of $$$<$$$ to the right of $$$p$$$ (in increasing order).
We use $$$right$$$ and $$$left$$$ to describe the trace of the pinball:
The first segment: the pinball moves from $$$right_1$$$ to $$$left_1$$$;
The second segment: the pinball moves from $$$left_1$$$ to $$$right_2$$$;
The third segment: the pinball moves from $$$right_2$$$ to $$$left_3$$$;
$$$\ldots$$$
The $$$2k$$$-th segment: the pinball moves from $$$left_k$$$ to the left boundary.
It is not difficult to observe that we can use prefix sum to store the sum of indices, and then quickly calculate the time when the pinball moves.
#include<bits/stdc++.h>
using namespace std;
#define MOD 1000000007
#define MODD 998244353
long long int bigmod(long long int a,long long int b){
long long int ans=1,powa=a;
while(b>0){
if(b%2==1){
ans*=powa;
ans%=MOD;
}
powa=powa*powa;
powa%=MOD;
b/=2;
}
return ans;
}
void func(){
int n;
cin >> n;
int arr[n];
for(int i=0;i<n;i++){
cin >> arr[i];
}
bool b1=0,b2=0;
int ans=0;
for(int i=0;i<n;i++){
if((!b1)&&(!b2)){
if(arr[i]==0) continue;
ans++;
if(arr[i]<=2) b1=1;
}
else if(b1){
b1=0;
if(arr[i]<=2) continue;
ans++;
if(arr[i]<=4) b2=1;
}
else{
b2=0;
if(arr[i]==0) continue;
ans++;
if(arr[i]<=4) b1=1;
}
}
cout << ans << '\n';
return;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int t;
cin >> t;
while(t--){
func();
}
}
//i added the bigmod func to my code cause yes
#include <bits/stdc++.h>
using namespace std;
#define m_p make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
typedef long long ll;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
mt19937 rnf(2106);
const int N = 200005;
int n;
int a[N];
int dp[N];
void minh(int& x, int y)
{
x = min(x, y);
}
void solv()
{
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
int minu[2] = {N, N};
for (int i = 1; i <= n; ++i)
{
dp[i] = dp[i - 1] + 1;
if (a[i] == 0)
minh(dp[i], dp[i - 1]);
if (a[i] <= 2)
minh(dp[i], i + minu[1 - i % 2]);
if (a[i] <= 2)
minh(minu[i % 2], dp[i - 1] - i);
else if (a[i] > 4)
minu[0] = minu[1] = N;
}
cout << dp[n] << "\n";
}
int main()
{
#ifdef SOMETHING
freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
#endif // SOMETHING
ios_base::sync_with_stdio(false), cin.tie(0);
int tt = 1;
cin >> tt;
while (tt--)
{
solv();
}
return 0;
}
E Catch the Mole
In fact, you don't need to hire the same Pokemon more than once.
Consider graph building.
How to reduce the number of edges in the graph?
#include<bits/stdc++.h>
using namespace std;
#define all(a) a.begin(),a.end()
#define pb push_back
#define sz(a) ((int)a.size())
using ll=long long;
using u32=unsigned int;
using u64=unsigned long long;
using i128=__int128;
using u128=unsigned __int128;
using f128=__float128;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
template<typename T> using vc=vector<T>;
template<typename T> using vvc=vc<vc<T>>;
template<typename T> using vvvc=vc<vvc<T>>;
using vi=vc<int>;
using vll=vc<ll>;
using vvi=vc<vi>;
using vvll=vc<vll>;
#define vv(type,name,n,...) \
vector<vector<type>> name(n,vector<type>(__VA_ARGS__))
#define vvv(type,name,n,m,...) \
vector<vector<vector<type>>> name(n,vector<vector<type>>(m,vector<type>(__VA_ARGS__)))
template<typename T> using min_heap=priority_queue<T,vector<T>,greater<T>>;
template<typename T> using max_heap=priority_queue<T>;
// https://trap.jp/post/1224/
#define rep1(n) for(ll i=0; i<(ll)(n); ++i)
#define rep2(i,n) for(ll i=0; i<(ll)(n); ++i)
#define rep3(i,a,b) for(ll i=(ll)(a); i<(ll)(b); ++i)
#define rep4(i,a,b,c) for(ll i=(ll)(a); i<(ll)(b); i+=(c))
#define cut4(a,b,c,d,e,...) e
#define rep(...) cut4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define per1(n) for(ll i=((ll)n)-1; i>=0; --i)
#define per2(i,n) for(ll i=((ll)n)-1; i>=0; --i)
#define per3(i,a,b) for(ll i=((ll)a)-1; i>=(ll)(b); --i)
#define per4(i,a,b,c) for(ll i=((ll)a)-1; i>=(ll)(b); i-=(c))
#define per(...) cut4(__VA_ARGS__,per4,per3,per2,per1)(__VA_ARGS__)
#define rep_subset(i,s) for(ll i=(s); i>=0; i=(i==0?-1:(i-1)&(s)))
template<typename T, typename S> constexpr T ifloor(const T a, const S b){return a/b-(a%b&&(a^b)<0);}
template<typename T, typename S> constexpr T iceil(const T a, const S b){return ifloor(a+b-1,b);}
template<typename T>
void sort_unique(vector<T> &vec){
sort(vec.begin(),vec.end());
vec.resize(unique(vec.begin(),vec.end())-vec.begin());
}
template<typename T, typename S> constexpr bool chmin(T &a, const S b){if(a>b) return a=b,true; return false;}
template<typename T, typename S> constexpr bool chmax(T &a, const S b){if(a<b) return a=b,true; return false;}
template<typename T, typename S> istream& operator >> (istream& i, pair<T,S> &p){return i >> p.first >> p.second;}
template<typename T, typename S> ostream& operator << (ostream& o, const pair<T,S> &p){return o << p.first << ' ' << p.second;}
#ifdef i_am_noob
#define bug(...) cerr << "#" << __LINE__ << ' ' << #__VA_ARGS__ << "- ", _do(__VA_ARGS__)
template<typename T> void _do(vector<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(set<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(unordered_set<T> x){for(auto i: x) cerr << i << ' ';cerr << "\n";}
template<typename T> void _do(T && x) {cerr << x << endl;}
template<typename T, typename ...S> void _do(T && x, S&&...y) {cerr << x << ", "; _do(y...);}
#else
#define bug(...) 777771449
#endif
template<typename T> void print(vector<T> x){for(auto i: x) cout << i << ' ';cout << "\n";}
template<typename T> void print(set<T> x){for(auto i: x) cout << i << ' ';cout << "\n";}
template<typename T> void print(unordered_set<T> x){for(auto i: x) cout << i << ' ';cout << "\n";}
template<typename T> void print(T && x) {cout << x << "\n";}
template<typename T, typename... S> void print(T && x, S&&... y) {cout << x << ' ';print(y...);}
template<typename T> istream& operator >> (istream& i, vector<T> &vec){for(auto &x: vec) i >> x; return i;}
vvi read_graph(int n, int m, int base=1){
vvi adj(n);
for(int i=0,u,v; i<m; ++i){
cin >> u >> v,u-=base,v-=base;
adj[u].pb(v),adj[v].pb(u);
}
return adj;
}
vvi read_tree(int n, int base=1){return read_graph(n,n-1,base);}
template<typename T, typename S> pair<T,S> operator + (const pair<T,S> &a, const pair<T,S> &b){return {a.first+b.first,a.second+b.second};}
template<typename T> constexpr T inf=0;
template<> constexpr int inf<int> = 0x3f3f3f3f;
template<> constexpr ll inf<ll> = 0x3f3f3f3f3f3f3f3f;
template<typename T> vector<T> operator += (vector<T> &a, int val){for(auto &i: a) i+=val; return a;}
template<typename T> T isqrt(const T &x){T y=sqrt(x+2); while(y*y>x) y--; return y;}
#define ykh mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
//#include<atcoder/all>
//using namespace atcoder;
//using mint=modint998244353;
//using mint=modint1000000007;
struct Tree{
int n;
vector<vector<int>> adj,anc;
vector<int> par,tl,tr,dep,ord,siz,ch,head;
Tree(int _n=0){
n=_n;
adj.resize(n);
}
void add_edge(int u, int v){
adj[u].push_back(v);
adj[v].push_back(u);
}
void init(){
par.resize(n),tl.resize(n),tr.resize(n),dep.resize(n),anc.resize(n),siz.resize(n),ch.resize(n),head.resize(n);
int cur=-1,m=0;
while((1<<m)<=n) m++;
for(int i=0; i<n; ++i) anc[i].resize(m),ch[i]=-1;
auto dfs1=[&](auto &self, int u, int fa) -> void{
par[u]=fa;
siz[u]=1;
for(int v: adj[u]) if(v!=fa) self(self,v,u),siz[u]+=siz[v];
for(int v: adj[u]) if(v!=fa&&(ch[u]==-1||siz[v]>siz[ch[u]])) ch[u]=v;
};
auto dfs2=[&](auto &self, int u, int fa) -> void{
ord.push_back(u);
tl[u]=++cur;
anc[u][0]=fa;
if(fa==-1) dep[u]=0;
else dep[u]=dep[fa]+1;
for(int i=1; i<m; ++i){
if(anc[u][i-1]==-1) anc[u][i]=-1;
else anc[u][i]=anc[anc[u][i-1]][i-1];
}
if(ch[u]!=-1) self(self,ch[u],u);
for(int v: adj[u]) if(v!=fa&&v!=ch[u]) self(self,v,u);
tr[u]=cur;
};
dfs1(dfs1,0,-1);
dfs2(dfs2,0,-1);
head[0]=0;
for(int u: ord){
for(int v: adj[u]) if(v!=par[u]){
if(v==ch[u]) head[v]=head[u];
else head[v]=v;
}
}
}
bool is_anc(int u, int v){return tl[u]<=tl[v]&&tr[u]>=tr[v];}
int get_anc(int u, int x){
for(int i=anc[0].size()-1; i>=0; --i) if(u!=-1&&(x>>i&1)) u=anc[u][i];
return u;
}
int lca(int u, int v){
if(is_anc(u,v)) return u;
for(int i=anc[0].size()-1; i>=0; --i) if(anc[u][i]!=-1&&!is_anc(anc[u][i],v)) u=anc[u][i];
return par[u];
}
};
void ahcorz(){
int lft=150;
auto query=[&](int u){
assert(lft>0);
cout << "? " << u+1 << endl;
lft--;
int res; cin >> res; return res;
};
int n; cin >> n;
Tree tree(n);
rep(n-1){
int u,v; cin >> u >> v; u--,v--;
tree.add_edge(u,v);
}
tree.init();
vi vis(n);
auto fill_vis=[&](auto &self, int u){
if(vis[u]) return;
vis[u]=1;
for(int v: tree.adj[u]) if(v!=tree.par[u]) self(self,v);
};
vi ord(n); iota(all(ord),0);
sort(all(ord),[&](int i, int j){return tree.dep[i]<tree.dep[j];});
per(n){
int u=ord[i];
if(vis[u]) continue;
int v=u;
rep(_,(lft-1)/2-1){
if(v==0) break;
v=tree.par[v];
}
if(!query(v)){
fill_vis(fill_vis,v);
continue;
}
int x=tree.ord.back();
int m=tree.dep[u]-tree.dep[v]+1;
rep(_,m){
if(query(x)){
cout << "! " << x+1 << endl;
return;
}
if(!query(v)){
int y=tree.par[v];
if(y!=-1) y=tree.par[y];
if(y==-1) y=0;
cout << "! " << y+1 << endl;
return;
}
}
cout << "! 1" << endl;
return;
}
assert(0);
}
signed main(){
ios_base::sync_with_stdio(0),cin.tie(0);
cout << fixed << setprecision(20);
int t=1;
cin >> t;
while(t--) ahcorz();
}
F Polygonal Segments
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <bitset>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int N=1000010;
const int LOGN=28;
const ll TMD=0;
const ll INF=2147483647;
int T,n,q;
ll a[N];
//----------------------------------------------------------
struct INFO
{
int ans,l,r;
ll sum;
vector<int> lpos,rpos;
vector<ll> lsum,rsum;
};
struct nod
{
INFO info;
nod *lc,*rc;
};
struct Segtree
{
nod *root;
Segtree()
{
build(&root,1,n);
}
void newnod(nod **p,int l,int r)
{
*p=new nod;
(*p)->info.l=l;
(*p)->info.r=r;
(*p)->info.sum=(*p)->info.ans=0;
(*p)->lc=(*p)->rc=NULL;
}
INFO merge_info(INFO x,INFO y)
{
INFO z;
z.l=x.l;
z.r=y.r;
z.sum=x.sum+y.sum;
z.ans=max(x.ans,y.ans);
int px=(int)x.lpos.size()-1,py=0;
ll mx=0;
//
//return z;
//
//
while(1) //two pointer
{
int len=0;
ll sum=0;
if(px<0)
{
sum+=x.sum;
len+=(x.r-x.l+1);
}
else
{
sum+=x.lsum[px]-a[x.lpos[px]];
len+=(x.r-x.lpos[px]);
}
if(py<y.rpos.size())
{
sum+=y.rsum[py]-a[y.rpos[py]];
len+=(y.rpos[py]-y.l);
}
else
{
sum+=y.sum;
len+=(y.r-y.l+1);
}
if(sum>2*mx) z.ans=max(z.ans,len);
if(px<0&&py>=y.rpos.size()) break;
else if(px<0) mx=max(mx,a[y.rpos[py]]),py++;
else if(py>=y.rpos.size()) mx=max(mx,a[x.lpos[px]]),px--;
else if(a[x.lpos[px]]<a[y.rpos[py]]) mx=max(mx,a[x.lpos[px]]),px--;
else mx=max(mx,a[y.rpos[py]]),py++;
}
//
/*
z.lpos.resize(1);
z.rpos.resize(1);
z.lsum.resize(1);
z.rsum.resize(1);
*/
//
if(z.ans<3) z.ans=-1;
for(int i=0;i<x.lpos.size();i++)
if(2*a[x.lpos[i]]>=x.lsum[i]+y.sum) z.lpos.push_back(x.lpos[i]),z.lsum.push_back(x.lsum[i]+y.sum);
for(int i=0;i<y.lpos.size();i++)
z.lpos.push_back(y.lpos[i]),z.lsum.push_back(y.lsum[i]);
for(int i=0;i<x.rpos.size();i++)
z.rpos.push_back(x.rpos[i]),z.rsum.push_back(x.rsum[i]);
for(int i=0;i<y.rpos.size();i++)
if(2*a[y.rpos[i]]>=y.rsum[i]+x.sum) z.rpos.push_back(y.rpos[i]),z.rsum.push_back(y.rsum[i]+x.sum);
//
return z;
}
void build(nod **p,int L,int R)
{
newnod(p,L,R);
if(L==R)
{
(*p)->info.sum=a[L];
(*p)->info.ans=-1;
(*p)->info.lpos.push_back(L);
(*p)->info.rpos.push_back(L);
(*p)->info.lsum.push_back(a[L]);
(*p)->info.rsum.push_back(a[L]);
return ;
}
int M=(L+R)>>1;
build(&(*p)->lc,L,M);
build(&(*p)->rc,M+1,R);
(*p)->info=merge_info((*p)->lc->info,(*p)->rc->info);
}
void modify(int pos,ll val)
{
_modify(root,pos,val);
}
void _modify(nod *p,int pos,ll val)
{
if(p->info.l==p->info.r)
{
p->info.sum=val;
p->info.lpos[0]=pos;
p->info.rpos[0]=pos;
p->info.lsum[0]=val;
p->info.rsum[0]=val;
return ;
}
int M=(p->info.l+p->info.r)>>1;
if(pos<=M) _modify(p->lc,pos,val);
else _modify(p->rc,pos,val);
p->info=merge_info(p->lc->info,p->rc->info);
}
ll getans(int L,int R)
{
return _getans(root,L,R).ans;
}
INFO _getans(nod *p,int L,int R)
{
if(p->info.l==L&&p->info.r==R) return p->info;
int M=(p->info.l+p->info.r)>>1;
if(R<=M) return _getans(p->lc,L,R);
else if(L>M) return _getans(p->rc,L,R);
else return merge_info(_getans(p->lc,L,M),_getans(p->rc,M+1,R));
}
};
//----------------------------------------------------------
int main()
{
//freopen("test.in","r",stdin);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
Segtree TR;
for(int i=1;i<=q;i++)
{
int t;
scanf("%d",&t);
if(t==1)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%I64d\n",TR.getans(l,r));
}
else
{
int p;
ll x;
scanf("%d%I64d",&p,&x);
a[p]=x;
TR.modify(p,x);
}
}
}
//fclose(stdin);
return 0;
}
// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include "bits/stdc++.h"
using namespace std;
using ll = long long int;
mt19937_64 RNG(chrono::high_resolution_clock::now().time_since_epoch().count());
/**
* Point-update Segment Tree
* Source: kactl
* Description: Iterative point-update segment tree, ranges are half-open i.e [L, R).
* f is any associative function.
* Time: O(logn) update/query
*/
template<class T, T unit = T()>
struct SegTree {
T f(T a, T b) {
a[0] += b[0];
if (a[1] < b[1]) a[1] = b[1], a[2] = b[2];
return a;
}
vector<T> s; int n;
SegTree(int _n = 0, T def = unit) : s(2*_n, def), n(_n) {}
void update(int pos, T val) {
for (s[pos += n] = val; pos /= 2;)
s[pos] = f(s[pos * 2], s[pos * 2 + 1]);
}
T query(int b, int e) {
T ra = unit, rb = unit;
for (b += n, e += n; b < e; b /= 2, e /= 2) {
if (b % 2) ra = f(ra, s[b++]);
if (e % 2) rb = f(s[--e], rb);
}
return f(ra, rb);
}
};
#include <ext/pb_ds/assoc_container.hpp>
struct splitmix64_hash {
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
template <typename K, typename V, typename Hash = splitmix64_hash>
using hash_map = __gnu_pbds::gp_hash_table<K, V, Hash>;
template <typename K, typename Hash = splitmix64_hash>
using hash_set = hash_map<K, __gnu_pbds::null_type, Hash>;
int main()
{
ios::sync_with_stdio(false); cin.tie(0);
int t; cin >> t;
while (t--) {
int n, q; cin >> n >> q;
vector<ll> a(n);
for (auto &x : a) cin >> x;
map<ll, int> cache;
struct Node {
int L, R, M; // [L, R)
set<array<int, 2>> by_l, by_r;
void ins(int l, int r) {
by_l.insert({l, r});
by_r.insert({r, l});
}
void del(int l, int r) {
by_l.erase({l, r});
by_r.erase({r, l});
}
};
vector<Node> ITree(4*n);
auto build = [&] (const auto &self, int node, int l, int r) -> void {
int mid = (l + r)/2;
ITree[node].L = l;
ITree[node].R = r;
ITree[node].M = mid;
if (l+1 == r) return;
self(self, 2*node + 1, l, mid);
self(self, 2*node + 2, mid, r);
};
build(build, 0, 0, n);
auto insert = [&] (const auto &self, int node, int l, int r) -> void { // Insert interval [l, r) into the tree
if (ITree[node].L+1 == ITree[node].R) {
ITree[node].ins(l, r);
return;
}
if (l >= ITree[node].M) self(self, 2*node+2, l, r);
else if (r <= ITree[node].M) self(self, 2*node+1, l, r);
else ITree[node].ins(l, r);
};
auto erase = [&] (const auto &self, int node, int x) -> void { // Delete all intervals covering point x
if (x < ITree[node].M) {
// Delete some prefix
auto &st = ITree[node].by_l;
while (!st.empty()) {
auto [l, r] = *begin(st);
if (l <= x) {
ITree[node].del(l, r);
ll id = 1ll*(n+1)*l + r;
cache.erase(id);
}
else break;
}
}
else {
// Delete some suffix
auto &st = ITree[node].by_r;
while (!st.empty()) {
auto [r, l] = *rbegin(st);
if (r > x) {
ITree[node].del(l, r);
ll id = 1ll*(n+1)*l + r;
cache.erase(id);
}
else break;
}
}
if (ITree[node].L+1 == ITree[node].R) return;
if (x < ITree[node].M) self(self, 2*node+1, x);
else self(self, 2*node+2, x);
};
constexpr array<ll, 3> unit = {0, 0, -1};
SegTree<array<ll, 3>, unit> seg(n);
for (int i = 0; i < n; ++i) seg.update(i, array<ll, 3>{a[i], a[i], i});
auto solve = [&] (const auto &self, int L, int R) -> int {
if (R-L <= 2) return -1;
ll id = 1ll*L*(n+1) + R;
if (cache.find(id) != cache.end()) return cache[id];
auto [sm, mx, pivot] = seg.query(L, R);
insert(insert, 0, L, R);
if (mx < sm - mx) {
return cache[id] = R-L;
}
else {
int ret = self(self, L, pivot);
ret = max(ret, self(self, pivot+1, R));
return cache[id] = ret;
}
};
while (q--) {
int type; cin >> type;
if (type == 1) {
int l, r; cin >> l >> r;
cout << solve(solve, l-1, r) << '\n';
}
else {
ll pos, val; cin >> pos >> val; --pos;
erase(erase, 0, pos);
if (pos) erase(erase, 0, pos-1);
if (pos+1 < n) erase(erase, 0, pos+1);
seg.update(pos, array<ll, 3>{val, val, pos});
}
}
}
}