当前位置: 首页 > 工具软件 > Hilo > 使用案例 >

P7988-[USACO21DEC] HILO G【set,线段树】

马胜泫
2023-12-01

正题

题目链接:https://www.luogu.com.cn/problem/P7988


题目大意

给出一个长度为 n n n的排列,开始有一个数字 x x x,第一次询问回答 x < a 1 x<a_1 x<a1(记为 L O LO LO)或者 x > a 1 x>a_1 x>a1(记为 H I HI HI),然后继续往后问,如果 a i a_i ai不在范围内就不询问,求对于每个 k ∈ [ 0 , n ] , x = k + 0.5 k\in [0,n],x=k+0.5 k[0,n],x=k+0.5时回答串中 H I L O HILO HILO的个数。

1 ≤ n ≤ 2 × 1 0 5 1\leq n\leq 2\times 10^5 1n2×105


解题思路

所有数一起考虑,考虑到序列里的每个询问 a i a_i ai只有当数字所在的区间包含 a i a_i ai时才会询问,然后 a i a_i ai会把一个区间成两个。

那么先考虑 H I HI HI,假设第 i i i个询问是 H I HI HI,那么首先肯定有 x < a i x< a_i x<ai,然后有 x > a j ( j ∈ [ 1 , i − 1 ] , a j ≤ a i ) x>a_j(j\in[1,i-1],a_j\leq a_i) x>aj(j[1,i1],ajai)也就是还要在 a i a_i ai目前在的区间内。

之后考虑这个 H I HI HI的下一个能否是 L O LO LO,首先它的下一个被询问的位置肯定是在 [   m a x { a j } , a i   ] [\ max\{a_j\},a_i\ ] [ max{aj},ai ]这个范围内的 a k a_k ak。然后我们要的 x x x就在 [ a k , a i ] [a_k,a_i] [ak,ai]范围内。

s e t set set求出每个 a i a_i ai对应的 m a x { a j } max\{a_j\} max{aj}让,然后反过来做用线段树维护 a k a_k ak就好了。

时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int N=2e5+10;
int n,a[N],l[N],s[N],w[N<<2];
set<int> pre;
void Change(int x,int L,int R,int pos,int val){
	w[x]=val;
	if(L==R)return;
	int mid=(L+R)>>1;
	if(pos<=mid)Change(x*2,L,mid,pos,val);
	else Change(x*2+1,mid+1,R,pos,val);
	return;
}
int Ask(int x,int L,int R,int l,int r){
	if(L==l&&R==r)return w[x];
	int mid=(L+R)>>1;
	if(r<=mid)return Ask(x*2,L,mid,l,r);
	if(l>mid)return Ask(x*2+1,mid+1,R,l,r);
	return min(Ask(x*2,L,mid,l,mid),Ask(x*2+1,mid+1,R,mid+1,r));
}
int main()
{
	scanf("%d",&n);
	pre.insert(0);pre.insert(n+1);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		l[i]=*(--pre.upper_bound(a[i]));
		pre.insert(a[i]);
	}
	for(int i=0;i<=n+1;i++)
		Change(1,0,n+1,i,n+1);
	for(int i=n;i>=1;i--){
		int k=a[Ask(1,0,n+1,l[i],a[i])];
		if(k){
			s[a[Ask(1,0,n+1,l[i],a[i])]]++;
			s[a[i]]--;
		}
		Change(1,0,n+1,a[i],i);
	}
	for(int i=1;i<=n;i++)s[i]+=s[i-1];
	for(int i=0;i<=n;i++)printf("%d\n",s[i]);
	return 0;
}
 类似资料: