传送门
题目描述
马老板的亲朋好友都来参加今天的欢庆宴会,入场时他们排起了一条长队。虽然他们来自不同的种族,但是他们有着一个共同的特点,不喜欢有年纪比自己小的人跟在自己的后面,这样会显得他们比较老。现在我们要找出在他们后面的年纪比他小的人和他最多间隔多少人。
分析
这道题做法挺多的,单调队列+二分的做法也能过,但是感觉线段树更好写一点
我们去动态维护每个点的值,然后去查找最左端的小于a[i]的值,然后插入更新即可
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
int a[N];
int n;
int ans[N];
struct Node{
int l,r;
int minv;
}tr[N * 4];
void build(int u,int l,int r){
tr[u] = {l,r,INF};
if(l ==r){
return;
}
int mid = l + r >> 1;
build(u << 1,l,mid);
build(u << 1 | 1,mid + 1,r);
return;
}
void push(int u){
tr[u].minv = min(tr[u << 1].minv,tr[u << 1 | 1].minv);
}
int query(int u,int x){
if(tr[u].l == tr[u].r) return tr[u].l;
int mid = tr[u].l + tr[u].r >> 1;
if(tr[u << 1].minv < x) return query(u << 1,x);
if(tr[u << 1 | 1].minv < x) return query(u << 1 | 1,x);
}
void modify(int u,int x,int p){
if(tr[u].l == tr[u].r){
tr[u].minv = p;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(u << 1,x,p);
else modify(u << 1 | 1,x,p);
push(u);
}
int main(){
scanf("%d",&n);
build(1,1,n);
for(int i = n;i;i--)
scanf("%d",&a[i]);
for(int i = 1;i <= n;i++){
if(tr[1].minv >= a[i]){
ans[i] = -1;
}
else{
ans[i] = i - query(1,a[i]) - 1;
}
modify(1,i,a[i]);
}
for(int i = n;i;i--) printf("%d ",ans[i]);
return 0;
}
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/