CF484-E. Sign on Fence

Posted by SergiuGothic on Thu, 23 Dec 2021 11:40:55 +0100

Portal
Given length is N N Array of N
Several triples { l , r , w } \{l,r,w\} {l,r,w} is required in the original array l l l ~ r r In r interval (left and right closed interval), the length is just w w Maximum rectangle height of w

analysis

There is monotonicity in finding the maximum value of this problem
If the current answer is x x When x, you can find the length exactly w w The rectangle of w, then ∀ y < = x \forall{y<=x} ∀ y < = x is feasible, and the length of w w Rectangle of w,

So for a query, you can l e n ∗ l o g ( m a x ) len*log(max) Find the answer within the time of len * log(max),
l e n len len is the interval length, that is, whether there is continuity in the interval every time w w Complexity of w values less than or equal to the current decision answer
Multiple queries, m ∗ l e n ∗ l o g ( m a x ) m*len*log(max) m * len * log(max) is obviously unacceptable
However, we find that for each query, we will judge by dichotomy, and the final decision answer is either on the left or on the right. Therefore, there is monotony of decision-making, and the overall dichotomy can be considered

We regard inquiry as a collection! It is called the question set, and the answer interval is called the solution set!
The initial query is in a query set, and the solution set is in the initial value set (sorted)
Two points. Dichotomize the solution set and make decisions on the question set
For each query
If it is determined that the solution is on the left, it is placed in the left temporary question set
If it is on the right, it will be placed in the temporary question set on the right

In this way, the answer can be processed recursively
Similar questions are

Details:
Because each time it is maintained according to the number of 01 sequence segments
The segment tree needs to be emptied, but if the operation complexity of divide and conquer is proportional to the interval length, the efficiency is the worst, so we have to consider reducing the complexity
We consider the points at each location that will affect the decision each time.

If a point has an impact on this dichotomy
For the question set whose decision is on the left solution set, the value of this point must be greater than the value of the left solution set, that is, this point is always a fixed value and does not need to be updated. Therefore, give small points to the left solution set, and these points can update the value on the left. Similarly, the same is true on the right

code

Code pass

//CF484E 
/*
  @Author: YooQ
*/
#include <bits/stdc++.h>
using namespace std;
#define sc scanf
#define pr printf
#define ll long long
#define int long long
#define FILE_OUT freopen("out", "w", stdout);
#define FILE_IN freopen("in", "r", stdin);
#define debug(x) cout << #x << ": " << x << "\n";
#define AC 0
#define WA 1
#define INF 0x3f3f3f3f
const ll MAX_N = 1e6+5;
const ll MOD = 1e9+7;
int N, M, K;
 
int arr[MAX_N];
bool brr[MAX_N];
int uni[MAX_N];
int ucnt = 0;
 
struct Tr {
	int k, l, r, len;
	Tr operator + (const Tr& B) const {
		Tr res;
		res.len = len + B.len;
		res.k = max(max(k, B.k), r + B.l);
		res.l = (l==len)?l+B.l:l;
		res.r = (B.r==B.len)?B.r+r:B.r;
		return res;
	}
}tr[MAX_N];
 
void push_up(int rt) {
	tr[rt] = tr[rt<<1] + tr[rt<<1|1];
}
 
void build(int rt, int l, int r) {
	tr[rt].len = r - l + 1;
	if (l == r) {
		tr[rt].k = tr[rt].l = tr[rt].r = 0;
		return;
	}
	int mid = l + ((r-l)>>1);
	build(rt<<1, l, mid);
	build(rt<<1|1, mid+1, r);
	push_up(rt);
}
 
void update(int rt, int l, int r, int x, int k) {
	if (l == r) {
		tr[rt].k = tr[rt].l = tr[rt].r = k;
		return;
	}
	int mid = l + ((r-l)>>1);
	if (x <= mid) update(rt<<1, l, mid, x, k);
	if (x  > mid) update(rt<<1|1, mid+1, r, x, k);
	push_up(rt);
}
 
Tr query(int rt, int l, int r, int x, int y) {
	if (x <= l && r <= y) {
		return tr[rt];
	}
	int mid = l + ((r-l)>>1);
	if (y <= mid) return query(rt<<1, l, mid, x, y);
	if (x  > mid) return query(rt<<1|1, mid+1, r, x, y);
	return query(rt<<1, l, mid, x, y) + query(rt<<1|1, mid+1, r, x, y);
}
 
struct Qr{
	int id, l, r, w;
}qr[MAX_N], tmp[MAX_N];
int ans[MAX_N];
 
struct Point{
	int id, x;
}point[MAX_N], tmp2[MAX_N];
 
void div(int l, int r, int x, int y, int px, int py) {
	if (l > r) return;
	int mid = l + ((r-l)>>1);
	
	int lp = px;
	int rp = py;
	for (int i = px; i <= py; ++i) {
		if (point[i].x >= uni[mid]) {
			tmp2[rp--] = point[i];
			update(1, 1, N, point[i].id, 1);
		} else {
			tmp2[lp++] = point[i];
		}
	}
	for (int i = px; i <= py; ++i) {
		point[i] = tmp2[i];
	}
	
	int lx = x;
	int rx = y;
	for (int i = x; i <= y; ++i) {
		if (query(1, 1, N, qr[i].l, qr[i].r).k >= qr[i].w) {
			ans[qr[i].id] = uni[mid];
			tmp[rx--] = qr[i];
		} else {
			tmp[lx++] = qr[i];
		}
	}
	for (int i = x; i <= y; ++i) {
		qr[i] = tmp[i];
	}
	div(l, mid-1, x, lx-1, px, lp-1);
	for (int i = px; i <= py; ++i) {
		if (point[i].x >= uni[mid]) {
			update(1, 1, N, point[i].id, 0);
		}
	}
	div(mid+1, r, lx, y, lp, py);
}
 
void solve(){
	sc("%lld", &N);
	for (int i = 1; i <= N; ++i) {
		sc("%lld", &arr[i]);
		point[i] = {i, arr[i]};
		uni[++ucnt] = arr[i];
	}
	
	sort(uni+1, uni+1+ucnt);
	ucnt = unique(uni+1, uni+1+ucnt) - uni - 1;
	
	sc("%lld", &M);
	for (int i = 1; i <= M; ++i) {
		qr[i].id = i;
		sc("%lld%lld%lld", &qr[i].l, &qr[i].r, &qr[i].w);
	}
	
	build(1, 1, N);
	
	div(1, ucnt, 1, M, 1, N);
	
	for (int i = 1; i <= M; ++i) {
		pr("%lld\n", ans[i]);
	}
}
 
signed main()
{
	#ifndef ONLINE_JUDGE
	//FILE_IN
	FILE_OUT
	#endif
	int T = 1;//cin >> T;
	while (T--) solve();
 
	return AC;
}

Topics: Algorithm data structure Binary Search