线段树求调
查看原帖
线段树求调
498612
Saka_Noa楼主2022/10/3 18:25

pre[x][1/2]pre[x][1/2] 表示正/负前缀
tail[x][1/2]tail[x][1/2] 表示正/负后缀
sum[x]sum[x] 表示区间乘
tmax[x]tmax[x] 表示区间最大值

#include<bits/stdc++.h>
#define lc k << 1
#define rc k << 1 | 1
#define lcon lc , l , mid
#define rcon rc , mid + 1 , r
#define Mid int mid = (l + r) >> 1
#define f(i , a , b) for(int i = a;i <= b;i++)
#define t(i , a , b) for(int i = a;i >= b;i--)
#define N 2500003
using namespace std;

struct node{
	long long pl[3] , tl[3];
	long long sm;
	long long tmx;
	
};
int n;
long long a[N];
long long tmax[N << 2] , pre[N << 2][3] , tail[N << 2][3] , sum[N << 1];
void pushup(int k) {
	/*tmax[k] = 0;
	pre[k][1] = tail[k][1] = pre[k][2] = tail[k][2] = 1;
	sum[k] = 1;*/
	
	
	tmax[k] = max(tmax[lc] , tmax[rc]);
	tmax[k] = max(tmax[k] , tail[lc][1] * pre[rc][1]);
	tmax[k] = max(tmax[k] , tail[lc][2] * pre[rc][2]);
	
	pre[k][1] = pre[lc][1];
	pre[k][2] = pre[lc][2];
	tail[k][1] = tail[rc][1];
	tail[k][2] = tail[rc][2];
	
	if(sum[lc] > 0)
	pre[k][1] = max(pre[k][1] , sum[lc] * pre[rc][1]);
	else 
	pre[k][1] = max(pre[k][1] , sum[lc] * pre[rc][2]);	
	
	if(sum[lc] > 0)
	pre[k][2] = min(pre[k][2] , sum[lc] * pre[rc][2]);
	else 
	pre[k][2] = min(pre[k][2] , sum[lc] * pre[rc][1]);
	
	if(sum[rc] > 0)
	tail[k][1] = max(tail[k][1] , sum[rc] * tail[lc][1]);
	else 
	tail[k][1] = max(tail[k][1] , sum[rc] * tail[lc][2]);	
	
	if(sum[rc] > 0)
	tail[k][2] = min(tail[k][2] , sum[rc] * tail[lc][2]);
	else 
	tail[k][2] = min(tail[k][2] , sum[rc] * tail[lc][1]);	
	
	sum[k] = sum[lc] * sum[rc];
}
void build(int k,int l , int r) {
	pre[k][1] = tail[k][1] = pre[k][2] = tail[k][2] = 1;
	if(l == r) {
		tmax[k] = a[l];
		sum[k] = a[l];
		if(a[l] > 0) pre[k][1] = tail[k][1] = a[l];
		else pre[k][2] = tail[k][2] = a[l];
		return;
	}
	Mid;
	build(lcon) , build(rcon);
	pushup(k);
}	
void update(int k , int l ,int r , int x , int v) {
	if(l == r && l == x) {
		pre[k][1] = tail[k][1] = pre[k][2] = tail[k][2] = 1;
		tmax[k] = v;
		sum[k] = v;
		if(v > 0) pre[k][1] = tail[k][1] = v;
		else pre[k][2] = tail[k][2] = v;
		return;
	}
	Mid;
	if(x <= mid) update(lcon , x , v);
	else update(rcon , x , v);
	pushup(k);
}

node query(int k , int l , int r , int x , int y) {
	node ans;
	if(x <= l && r <= y) {
		ans.pl[1] = pre[k][1];
		ans.pl[2] = pre[k][2];
		ans.tl[1] = tail[k][1];
		ans.tl[2] = tail[k][2];
		ans.sm = sum[k];
		ans.tmx = tmax[k];
		return ans;
	}
	
	Mid;
	if(x <= mid && y > mid) {
		ans = query(lcon , x , y);
		node ans2 = query(rcon , x , y) , Ans;
		Ans.tmx = max(ans.tmx , ans2.tmx);
		Ans.tmx = max(Ans.tmx , ans.tl[1] * ans2.pl[1]);
		Ans.tmx = max(Ans.tmx , ans.tl[2] * ans2.pl[2]);
		
		Ans.pl[1] = ans.pl[1];
		Ans.pl[2] = ans.pl[2];
		Ans.tl[1] = ans2.tl[1];
		Ans.tl[2] = ans2.tl[2];
		
		if(ans.sm > 0)
		Ans.pl[1] = max(Ans.pl[1] , ans.sm * ans2.pl[1]);
		else 
		Ans.pl[1] = max(Ans.pl[1] , ans.sm * ans2.pl[2]);	
		
		if(sum[lc] > 0)
		pre[k][2] = min(pre[k][2] , ans.sm * ans2.pl[2]);
		else 
		pre[k][2] = min(pre[k][2] , ans.sm * ans2.pl[1]);
		
		if(ans2.sm > 0)
		Ans.tl[1] = max(Ans.tl[1] , ans2.sm * ans.tl[1]);
		else 
		Ans.tl[1] = max(Ans.tl[1] , ans2.sm * ans.tl[2]);
		
		if(ans2.sm > 0)
		Ans.tl[2] = min(Ans.tl[2] , ans2.sm * ans.tl[2]);
		else 
		Ans.tl[2] = min(Ans.tl[2] , ans2.sm * ans.tl[1]);
		
		Ans.sm = ans.sm * ans2.sm;
		
		return Ans;
	}
	else if(x <= mid) return query(lcon , x , y);
	else if(y > mid) return query(rcon , x , y);
}
int Q;
int main() {	
	ios::sync_with_stdio(0);
	
	cin >> n >> Q;
	f(i , 1 , n) cin >> a[i];
	
	build(1 , 1 , n);
	
	//f(i , 1 , n) f(j , i , n) printf("l:%d r:%d ans:%lld preN:%lld tailN:%lld preZ:%lld tailZ:%lld\n" , i , j , query(1 , 1 , n , i  , j).tmx , query(1 , 1 , n , i  , j).pl[1] , query(1 , 1 , n , i  , j).tl[1] ,  query(1 , 1 , n , i  , j).pl[2] , query(1 , 1 , n , i  , j).tl[2]);
	
	while(Q--) {
		int x , y , z;
		cin >> x >> y >> z;
		if(x == 1) {
			update(1 , 1 , n , y , z);
			
			/*cout << " \n";
			f(i , 1 , n) f(j , i , n) printf("l:%d r:%d ans:%lld \n" , i , j , query(1 , 1 , n , i  , j).tmx);
			cout << "\n ";*/
			
		} else {
			//cout << y << " " << z << " ";
			node ans = query(1 , 1 , n , y , z);
			long long answer = max(ans.tmx , max(ans.pl[1] , ans.tl[1]));
			if(answer > 1073741824) cout << "Too large\n";
			else cout << max(answer , (long long)1) << "\n";
		}
	}
	
	/*cout << " \n";
	f(i , 1 , n) f(j , i , n) printf("l:%d r:%d ans:%lld \n" , i , j , query(1 , 1 , n , i  , j).tmx);
	cout << "\n ";*/
	
	return 0;
}
2022/10/3 18:25
加载中...