[CF1539F] Strange Array

Posted by hexguy on Fri, 28 Jan 2022 08:01:17 +0100

Problem surface

There is a length of n \tt n Sequence of n a \tt a a. For each location i ∈ [ 1 , n ] \tt i\in[1,n] i∈[1,n]:

  • Select an interval [ l , r ] \tt[l,r] [l,r] satisfied 1 ≤ l ≤ i ≤ r ≤ n \tt1\leq l\leq i\leq r\leq n 1≤l≤i≤r≤n .
  • Put interval [ l , r ] \tt[l,r] Take out the number in [l,r] (obviously including a i \tt a_i ai), sort from small to large. Those with the same value can be arranged at will.
  • The middle position is defined as: { l e n g t h + 1 2 , ( l e n g t h   %   2 = 1 ) l e n g t h 2 + 1 , ( l e n g t h   %   2 = 0 ) \left\{\begin{array}{cc}\frac{\tt length+1}{2}, & (\tt length\,\%\,2=1)\\\frac{\tt length}{2}+1, & (\tt length\,\%\,2=0)\end{array}\right. {2length+1, 2length+1, (length%2=1)(length%2=0), i.e ⌈ l e n g t h + 1 2 ⌉ \tt\left\lceil\frac{length+1}{2}\right\rceil ⌈2length+1​⌉ .
  • position i \tt i The strangeness of i is ∣ a i Row order after of position Set − in between position Set ∣ \tt|a_i sorted position - middle position| ∣ ai − sorted position − middle position ∣.

give n \tt n n sum sequence a \tt a a. Each location i \tt i Selected interval of i [ l i , r i ] \tt[l_i,r_i] [li, ri] whatever, but you have to output the location i \tt i Maximum strangeness of i.

1 ≤ n ≤ 200   000   ,   1 ≤ a i ≤ n \tt1\leq n\leq 200\,000~,~1\leq a_i\leq n 1≤n≤200000 , 1≤ai​≤n .

Problem solution

definition S 1 \tt S_1 S1 = interval [ l , r ] \tt[l,r] Strictly less than in [l,r] a i \tt a_i The number of elements of ai +, S 2 \tt S_2 S2 = interval [ l , r ] \tt[l,r] Equal to in [l,r] a i \tt a_i The number of elements of ai (including itself), S 3 \tt S_3 S3 is interval [ l , r ] \tt[l,r] Strictly greater than in [l,r] a i \tt a_i The number of elements of ai , then the position i \tt i The strangeness of i is
max ⁡ { ( S 1 + S 2 ) − ⌈ ( S 1 + S 2 ) + S 3 + 1 2 ⌉ ⌈ S 1 + ( S 2 + S 3 ) + 1 2 ⌉ − ( S 1 + 1 ) \max\left\{\begin{matrix} \tt (S_1+S_2)-\left\lceil \frac{(S_1+S_2)+S_3+1}{2} \right\rceil\\ \tt \left\lceil \frac{S_1+(S_2+S_3)+1}{2} \right\rceil-(S_1+1) \end{matrix}\right. max⎩⎨⎧​(S1​+S2​)−⌈2(S1​+S2​)+S3​+1​⌉⌈2S1​+(S2​+S3​)+1​⌉−(S1​+1)​

Here I ignore the absolute value sign, because the first line is hypothetical a i \tt a_i ai is behind the middle position and the second line assumes the front. In these two cases, the use of the same elements as yourself is different, assuming a i \tt a_i ai , when in the back, try to put the same in the front (think they are better than a i \tt a_i ai ^ small), otherwise try to put them in the back (think they are smaller than a i \tt a_i ai (large). So there is the above formula.

Then we can find a property: at the same time, compared with a i \tt a_i ai large sum ratio a i \tt a_i ai # after subtracting the same number of elements from each small number, the answer remains the same. It is equivalent to pinching out a section of the same length before and after the sorted sequence (not removed) a i \tt a_i ai), now the middle position and a i \tt a_i The relative position of ai , remains unchanged and the degree of strangeness remains unchanged. This property is not difficult to understand. You can see from the above formula.

In that case, the information useful to us is only the difference between the two! As long as you know the difference, then assume the smaller one is 0 \tt0 0, then bring in the above formula, and the result is the same.

It may be considered that a i \tt a_i ai equals less than it. Next:

First consider only one location i \tt i i how to do it. We put less than a i \tt a_i The position of ai , is assigned as 1 \tt1 1. The position greater than it is assigned as − 1 \tt-1 − 1, processing prefixes and arrays s u m \tt sum sum, then ask ∣ s u m r − s u m l − 1 ∣ \tt|sum_r-sum_{l-1}| Maximum value of ∣ sumr − suml − 1 ∣. At this time, due to limited 1 ≤ l ≤ i ≤ r ≤ n \tt1\leq l\leq i\leq r\leq n 1 ≤ l ≤ i ≤ r ≤ n, we find the maximum or minimum in the range of the two s u m r \tt sum_r sumr# and s u m l − 1 \tt sum_{l-1} The value of suml − 1 can solve the problem.

If there are multiple locations i \tt i What about i? Ranking by value, establishing a chairman tree is a way, but it is not necessary. This problem is offline. We only need to calculate from small to large and maintain it on a segment tree at a time s u m \tt sum sum array and query are OK. It should be noted that all positions with the same value should be modified first, and then queried one by one.

Assumptions and a i \tt a_i If ai is equal to greater than it, it is the same, that is, the position with the same value needs to be queried and then modified.

Time complexity Θ ( n log ⁡ n ) \tt \Theta(n\log n) Θ(nlogn) .

CODE

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define DB double
#define LL long long
#define ENDL putchar('\n')
#define lowbit(x) ((-x) & (x))
LL read() {
	LL f=1,x=0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
int n,m,i,j,s,o,k;
int a[MAXN];
vector<int> bu[MAXN];
int tre[MAXN<<2],tre2[MAXN<<2],lz[MAXN<<2],M;
void maketree(int n) {
	M=1;while(M<n+2)M<<=1;
}
void addtree(int l,int r,int y) {
	if(l > r) return ;
	int s=M+l-1,t=M+r+1;
	while(s || t) {
		if(s<M) {
			tre[s] = max(tre[s<<1],tre[s<<1|1])+lz[s];
			tre2[s] = min(tre2[s<<1],tre2[s<<1|1])+lz[s];
		}
		if(t<M) {
			tre[t] = max(tre[t<<1],tre[t<<1|1])+lz[t];
			tre2[t] = min(tre2[t<<1],tre2[t<<1|1])+lz[t];
		}
		if((s>>1) ^ (t>>1)) {
			if(!(s & 1)) tre[s^1] += y,tre2[s^1] += y,lz[s^1] += y;
			if(t & 1) tre[t^1] += y,tre2[t^1] += y,lz[t^1] += y;
		}
		s >>= 1;t >>= 1;
	}
	return ;
}
int findmax(int l,int r) {
	if(l > r) return -0x3f3f3f3f;
	int s=M+l-1,t=M+r+1;
	int ls = -0x3f3f3f3f,rs = -0x3f3f3f3f;
	while(s || t) {
		if(s<M) ls += lz[s];
		if(t<M) rs += lz[t];
		if((s>>1) ^ (t>>1)) {
			if(!(s & 1)) ls = max(tre[s^1],ls);
			if(t & 1) rs = max(tre[t^1],rs);
		}
		s >>= 1;t >>= 1;
	}
	return max(ls,rs);
}
int findmin(int l,int r) {
	if(l > r) return 0x3f3f3f3f;
	int s=M+l-1,t=M+r+1;
	int ls = 0x3f3f3f3f,rs = 0x3f3f3f3f;
	while(s || t) {
		if(s<M) ls += lz[s];
		if(t<M) rs += lz[t];
		if((s>>1) ^ (t>>1)) {
			if(!(s & 1)) ls = min(tre2[s^1],ls);
			if(t & 1) rs = min(tre2[t^1],rs);
		}
		s >>= 1;t >>= 1;
	}
	return min(ls,rs);
}
int as[MAXN];
int main() {
	n = read();
	maketree(n);
	for(int i = 1;i <= n;i ++) {
		a[i] = read();
		bu[a[i]].push_back(i);
		addtree(i,n,-1);
	}
	for(int i = 1;i <= n;i ++) {
		for(int j = 0;j <(int)bu[i].size();j ++) { // -1 -> 1
			int y = bu[i][j];
			int ll = max(0,findmax(1,y-1)),rr = findmin(y,n);
			int mx = ll-rr;
			as[y] = max(as[y],(mx+2)/2-1);
		}
		for(int j = 0;j <(int)bu[i].size();j ++) {
			int y = bu[i][j];
			addtree(y,n,2);
		}
		for(int j = 0;j <(int)bu[i].size();j ++) {
			int y = bu[i][j];
			int ll = min(0,findmin(1,y-1)),rr = findmax(y,n);
			int mi = rr-ll;
			as[y] = max(as[y],mi-(mi+2)/2);
		}
	}
	for(int i = 1;i <= n;i ++) {
		printf("%d ",as[i]);
	}ENDL;
	return 0;
}

Topics: data structure CodeForces