CodeForces 91B Queue (线段树单点操作)

Description

There are n walruses standing in a queue in an airport. They are numbered starting from the queue‘s tail: the
1-st walrus stands at the end of the queue and the
n-th walrus stands at the beginning of the queue. The
i-th walrus has the age equal to ai.

The i-th walrus becomes displeased if there‘s a younger walrus standing in front of him, that is, if exists such
j (i?<?j), that
ai?>?aj. The
displeasure of the
i-th walrus is equal to the number of walruses between him and the furthest walrus ahead of him, which is younger than the
i-th one. That is, the further that young walrus stands from him, the stronger the displeasure is.

The airport manager asked you to count for each of n walruses in the queue his displeasure.

Input

The first line contains an integer n (2?≤?n?≤?105) — the number of walruses in the queue. The second line contains
integers ai (1?≤?ai?≤?109).

Note that some walruses can have the same age but for the displeasure to emerge the walrus that is closer to the head of the queue needs to be
strictly younger than the other one.

Output

Print n numbers: if the
i-th walrus is pleased with everything, print "-1" (without the quotes). Otherwise, print the
i-th walrus‘s displeasure: the number of other walruses that stand between him and the furthest from him younger walrus.

Sample Input

Input

6
10 8 5 3 50 45

Output

2 1 0 -1 0 -1 

Input

7
10 4 6 3 2 8 15

Output

4 2 1 0 -1 -1 -1 

Input

5
10 3 1 10 11

Output

1 0 -1 -1 -1 

线段树维护区间最小值, 循环一遍数组,每次找到比这个数小且在最右端的数,那么左边处理过的数可以更新成INF, 顺便更新最小值。那么查询之前, 先询问整个数组的最小是和当前值的比较,满足最小值小于当前值才有查询的必要,而且右边不成立就一定在左边。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <cmath>
#include <cctype>
#include <stack>
#include <queue>
#include <set>
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
using namespace std;
typedef __int64 LL;
const int maxn = 100005;
const int MAX = 0x3f3f3f3f;
int n, tg, b, k, a[maxn], mi[maxn << 2], ans[maxn];
void up(int o) {
    mi[o] = min(mi[o<<1], mi[o<<1|1]);
}
void build(int o, int l, int r) {
    if(l == r) {
        scanf("%d", &mi[o]);
        a[l] = mi[o];
        return;
    }
    int m = (l+r) >> 1;
    build(lson);
    build(rson);
    up(o);
}
void query(int o, int l, int r) {
    if(l == r) {
        ans[k++] = l - b - 1;
        return;
    }
    int m = (l+r) >> 1;
    if(mi[o<<1|1] < tg) query(rson);
    else query(lson);
}
void update(int o, int l, int r) {
    if(l == r) mi[o] = MAX;
    else {
        int m = (l+r) >> 1;
        if(b <= m) update(lson);
        else update(rson);
        up(o);
    }
}
int main()
{
    cin >> n;
    build(1, 1, n);
    for(int i = 1; i <= n; i++) {
        tg = a[i], b = i;
        update(1, 1, n);
        if(mi[1] >= tg) ans[k++] = -1;
        else query(1, 1, n);
    }
    for(int i = 0; i < k; i++) printf("%d ", ans[i]);
    return 0;
}



时间: 2024-12-15 01:35:30

CodeForces 91B Queue (线段树单点操作)的相关文章

HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:给你一个长度n的数列,初始都为0,有三种操作,第一种给第k个位置的数加d,第二种是查询区间 [l , r] 的总和,第三种是使区间 [l , r] 的值改为离它最近的那个斐波那契数的值. 我刚开始用sum数组存储节点的值,第三种操作是个区间更新,但是区间更新的值不一样,我就想当然的搜到最底部的节点来处理更新,果断T了.后来想了想,其实可以在节点上再加一个信息,就是这个值下次进行第三种操作要变

Uva 12299 RMQ with Shifts(线段树 + 单点更新 )

Uva 12299 RMQ with Shifts (线段树 + 单点更新) 题意: 对于给定的序列 x[i]给出一个操作 shift(a,b,c,d,e) 对应的是将 x[a]与x[b] x[b]与x[c] 这样相邻的两两交换For example, if A={6, 2, 4, 8, 5, 1, 4}then shift(2, 4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that,shift(1, 2) yields {8, 6, 4, 5, 4

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in

HDU2852_KiKi&#39;s K-Number(线段树/单点更新)

解题报告 题目传送门 题意: 意思很好理解. 思路: 每次操作是100000次,数据大小100000,又是多组输入.普通模拟肯定不行. 线段树结点记录区间里存在数字的个数,加点删点操作就让该点个数+1,判断x存在就查询[1,x]区间的个数和[1,x-1]的个数. 求x之后第k大的数就先确定小于x的个数t,第t+k小的数就是要求的. #include <iostream> #include <cstdio> #include <cstring> using namespa

HDU1754_I Hate It(线段树/单点更新)

解题报告 题意: 略 思路: 单点替换,区间最值 #include <iostream> #include <cstring> #include <cstdio> #define inf 99999999 using namespace std; int maxx[808000]; void update(int root,int l,int r,int p,int v) { int mid=(l+r)/2; if(l==r)maxx[root]=v; else if(

CodeForces 46DParking Lot线段树

#include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include <qu

HDU 1754 I Hate It (线段树 单点更新)

题目链接 中文题意,与上题类似. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <cstdlib> 6 #include <algorithm> 7 const int maxn = 200000+10; 8 using namespace std; 9 int a[maxn], n, m; 10

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p

线段树单点更新 hdu 1754 I Hate It

题意:给n个学生的成绩,可以动态修改某个学生的成绩,要求动态查询某个区间学生的成绩的最大值. 线段树单点更新题目,只需用一个数组存储当前节点对应的区间的成绩的最大值,并且把向上更新节点操作(pushup)改为更新该节点的两个子节点的最大值即可. 代码: