http://codeforces.com/problemset/problem/91/B

B. Queue

time limit per test:

2 seconds

memory limit per test:

256 megabytes

input:

standard input

output:

standard output

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.

Examples

input

     

output

   -  - 

input

      

output

    - - - 

input

    

output

  - - - 

题意:

给一个序列,对于第i个数字a[i],在右边找到一个比它小的数,并且最靠右的位置k,输出k-i-1,如果一个都找不到,输出-1。对于序列的每个元素都要输出。

解题思路:

可以用线段树,每个节点表示该段的最小值, 循环一遍数组,每个位置找到最靠右且比它小的数后(已经处理过),将其改为INF,并对线段树进行最小值更新。

查询之前, 先询问整个数组的最小值和当前值的比较,满足最小值小于当前值才有查询的必要,如果满足查询的条件,右边不成立就一定在左边。

上代码:

 #include <bits/stdc++.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const double eps =1e-;
const int mod=1e9+;
const int maxn=1e5+;
using namespace std; struct node
{
int l;
int r;
int val;
}Tr[maxn<<]; int a[maxn]; //存放数据
int ans[maxn]; //存放答案 void PushUp(int u)
{
Tr[u].val=min(Tr[u<<].val,Tr[u<<|].val);
} void Build(int l,int r,int u)
{
Tr[u].l=l; Tr[u].r=r; Tr[u].val=;
if(l==r)
{
Tr[u].val=a[l];
return ;
}
int mid=(l+r)>>;
Build(l,mid,u<<);
Build(mid+,r,u<<|);
PushUp(u);
} void Update(int u,int pos)
{
int l=Tr[u].l; int r=Tr[u].r;
if(l==r)
{
Tr[u].val=INF; //pos位置的答案已得出,将其变为INF
return ;
}
int mid=(l+r)>>;
if(pos<=mid)
Update(u<<,pos);
else
Update(u<<|,pos);
PushUp(u); //向上更新最小值
} void Query(int u,int pos)
{
int l=Tr[u].l; int r=Tr[u].r;
if(l==r)
{
ans[pos]=l-pos-; //得出pos位置的答案
return ;
}
int mid=(l+r)>>;
if(Tr[u<<|].val<a[pos]) //因为是最右边的最小值,先判断右边
Query(u<<|,pos);
else
Query(u<<,pos);
} int main()
{
#ifdef DEBUG
freopen("sample.txt","r",stdin);
#endif int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
Build(,n,);
for(int i=;i<=n;i++) //遍历求每一个答案
{
if(Tr[].val>=a[i]) ans[i]=-; //不满足查询条件
else Query(,i);
Update(,i); //更新最小值
}
for(int i=;i<=n;i++)
printf(i==n? "%d\n":"%d ",ans[i]); return ;
}

这题也可以用单调队列,从最后一个数开始处理,若该数比队列中最后一个都小,则是-1,并加入队尾,否则就对队列中的数进行二分(直接粘的题解,学完单调队列再回来填坑)

 #include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits> using namespace std; #define LL long long
const int INF=0x3f3f3f3f;
const int MAXN=; int a[MAXN],ans[MAXN];
int x[MAXN],p[MAXN]; int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=; i<=n; i++) scanf("%d",&a[i]);
int sum=;
for(int i=n; i>=; i--)
{
if(sum==||x[sum-]>=a[i])
{
x[sum]=a[i];
p[sum++]=i;
ans[i]=-;
}
else
{
int k,l=,r=sum-;
while(l<=r)
{
int mid=(l+r)>>;
if(x[mid]<a[i]) {k=mid;r=mid-;}
else l=mid+;
}
ans[i]=p[k]-i-;
}
}
printf("%d",ans[]);
for(int i=; i<=n; i++)
printf(" %d",ans[i]);
printf("\n");
}
return ;
}

以下题解来自于:https://www.cnblogs.com/sineatos/p/3870790.html

分析题目,我们发现题目需要我们求的值的要求有两个:①最右边的,②比当前考察的值小的。
  于是我们需要维护一个这样的序列,这个序列保存着已扫描的值里面的最小值,同时这个序列具有单调性,从开始到当前,序列需要保持递减,对于插入的时候如果无法保持序列的单调性的话,就不要需要插入的值,否则就插入。在求结果的时候,我们可以二分求出比考察点小的,里考察点最远(最右)的那个点,然后求出答案即可。

  这里记录一下维护序列单调性的两种方法:①要插入的元素一定会插入,通过抛弃原有的元素来保持单调性。②如果带插入的元素加入会打破单调性的话就不会插入到序列里面。
  如果用一个单调队列的维护一个序列,单调队列里面的元素是已经扫描过的元素的最值,次值,次次值······,同时,如果里面是拥有窗口的话,单调队列里面记录的元素可以是元素保存位置的下标,这样就可以更好地维护元素弹出。

  对于单调性的研究还需继续。

 #include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define MAX 100002
using namespace std; int a[MAX],ans[MAX];
vector<int> v,num; int main()
{
int n;
//freopen("data.txt","r",stdin);
while(~scanf("%d",&n)){
for(int i=;i<n;i++) scanf("%d",&a[i]);
v.clear();
num.clear();
for(int i=n-;i>=;i--){
if(v.size()== || v.back()>=a[i]){
v.push_back(a[i]); num.push_back(i);
ans[i]=-;
}else{
int j = (lower_bound(v.rbegin(),v.rend(),a[i]) - v.rbegin());
j = (int)v.size() - j - ;
ans[i] = num[j+] - i - ;
}
}
for(int i=;i<n;i++){
if(i) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return ;
} 91B

最新文章

  1. Possion 分布
  2. sql数剧操作语言
  3. libcurl上传文件,添加自定义头
  4. 窗体皮肤实现 - 实现简单Toolbar(六)
  5. 盗链网易163、腾讯QQ、新浪sina、百度Baidu的图片之PHP独立版
  6. C++相关资源
  7. Js 直接下载保存文件
  8. HMVC
  9. Make Hadoop 1.2.1 run, my first try
  10. Subquery returns more than 1 row
  11. phpstorm+wamp+xdebug配置php调试环境
  12. Linq To Object 函数介绍
  13. 通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象
  14. JavaScript: The Good Parts
  15. 编译android源码遇到错误及其解决方法
  16. Javascript调用WinForm方法
  17. django dispatch
  18. c++的bind1st()与bind2nd() 二元算子转一元算子
  19. HTML常用标签用法及实例
  20. roadhogrc.mock.js配置

热门文章

  1. part9 公用图片画廊组件拆分
  2. POJ 1129:Channel Allocation 四色定理+暴力搜索
  3. 设计模式讲解3:ChainOfResponsibility模式源码
  4. Mycat简介及适用场景
  5. Codeforces Round #622 (Div. 2)C2 Skyscrapers最大&quot;尖&quot;性矩形,思维||分治
  6. (综合)P2089 烤鸡
  7. TCP连接为什么三次握手四次挥手
  8. python 用 pycharm 光速下载各种包
  9. tomcat添加ssl证书
  10. Android studio个人常用快捷键