Codeforces 91B-Queue
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
The airport manager asked you to count for each of n
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
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 input6 10 8 5 3 50 45output
2 1 0 -1 0 -1input
7 10 4 6 3 2 8 15output
4 2 1 0 -1 -1 -1input
5 10 3 1 10 11output
1 0 -1 -1 -1
題意:給一個序列,對於第i個數字a[i],在右邊找到一個比它小的數,並且最靠右的位置k,輸出k-i-1,如果一個都找不到,輸出-1。對於序列的每個元素都要輸出。
解題思路:可以用線段樹,每個節點表示該段的最大值,每個位置找到最靠右且比它小的數後,將其改為INF,並對線段樹進行更新。也可以用單調佇列,從最後一個數開始處理,若該數比佇列中最後一個都小,則是-1,並加入隊尾,否則就對佇列中的數進行二分
線段樹
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
using namespace std;
#define INF 0x3f3f3f3f
int a[100090],tree[400060];
int n,ans[100090];
void build(int k,int l,int r)
{
if(l==r)
{
scanf("%d",&a[l]);
tree[k]=a[l];
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
tree[k]=min(tree[k<<1],tree[k<<1|1]);
}
void update(int k,int l,int r,int p)
{
if(l==r)
{
tree[k]=INF;
return;
}
int mid=(l+r)>>1;
if(p<=mid) update(k<<1,l,mid,p);
else update(k<<1|1,mid+1,r,p);
tree[k]=min(tree[k<<1],tree[k<<1|1]);
}
void query(int k, int l, int r,int p)
{
if(l==r)
{
ans[p]=l-p-1;
return;
}
int mid=(l+r)>>1;
if(tree[k<<1|1]<a[p]) query(k<<1|1,mid+1,r,p);
else query(k<<1,l,mid,p);
}
int main()
{
while(~scanf("%d",&n))
{
build(1,1,n);
for(int i=1; i<=n; i++)
{
if(tree[1]>=a[i]) ans[i]=-1;
else query(1,1,n,i);
update(1,1,n,i);
}
for(int i=1; i<n; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}
單調佇列
#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=1000010;
int a[MAXN],ans[MAXN];
int x[MAXN],p[MAXN];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; i++) scanf("%d",&a[i]);
int sum=0;
for(int i=n; i>=1; i--)
{
if(sum==0||x[sum-1]>=a[i])
{
x[sum]=a[i];
p[sum++]=i;
ans[i]=-1;
}
else
{
int k,l=0,r=sum-1;
while(l<=r)
{
int mid=(l+r)>>1;
if(x[mid]<a[i]) {k=mid;r=mid-1;}
else l=mid+1;
}
ans[i]=p[k]-i-1;
}
}
printf("%d",ans[1]);
for(int i=2; i<=n; i++)
printf(" %d",ans[i]);
printf("\n");
}
return 0;
}