E - Frequency(思维好题)

Problem Statement

Snuke loves constructing integer sequences.

There are NN piles of stones, numbered 11 through NN. The pile numbered ii consists of aiai stones.

Snuke will construct an integer sequence ss of length ΣaiΣai, as follows:

  1. Among the piles with the largest number of stones remaining, let xx be the index of the pile with the smallest index. Append xx to the end of ss.
  2. Select a pile with one or more stones remaining, and remove a stone from that pile.
  3. If there is a pile with one or more stones remaining, go back to step 1. Otherwise, terminate the process.

We are interested in the lexicographically smallest sequence that can be constructed. For each of the integers 1,2,3,...,N1,2,3,...,N, how many times does it occur in the lexicographically smallest sequence?

Constraints

  • 1≤N≤1051≤N≤105
  • 1≤ai≤1091≤ai≤109

Input

The input is given from Standard Input in the following format:

NN
a1a1 a2a2 ...... aNaN

Output

Print NN lines. The ii-th line should contain the number of the occurrences of the integer ii in the lexicographically smallest sequence that can be constructed.


Sample Input 1 Copy

Copy

2
1 2

Sample Output 1 Copy

Copy

2
1

The lexicographically smallest sequence is constructed as follows:

  • Since the pile with the largest number of stones remaining is pile 22, append 22 to the end of ss. Then, remove a stone from pile 22.
  • Since the piles with the largest number of stones remaining are pile 11 and 22, append 11 to the end of ss (we take the smallest index). Then, remove a stone from pile 22.
  • Since the pile with the largest number of stones remaining is pile 11, append 11 to the end of ss. Then, remove a stone from pile 11.

The resulting sequence is (2,1,1)(2,1,1). In this sequence, 11 occurs twice, and 22 occurs once.


Sample Input 2 Copy

Copy

10
1 2 1 3 2 4 2 5 8 1

Sample Output 2 Copy

Copy

10
7
0
4
0
3
0
2
3
0

题意:有N堆石头,每堆石头有Ai个石头,每次可从任意一堆石头中取出一个石头,然后取所有堆中石头个数最大的位置,放到序列S中,现在要将所有石头拿完,以构造一个序列S,并使得这个序列S的是字典序最小的,问,这个字典序最小的序列,每个数字1~N各出现了多少次。

对于多个最大堆的情况,肯定一直选位序最小的作为序列S中填入的数值。然后在保持这个最大堆的基础上,将该序号之前大于等于最大堆的石头都拿到和次大堆都一样的数量,当然最后拿的是之前一直塞到S序列中标号的那一堆。然后对于次大堆同样削去和次次大堆一样的层数。这个多出来的总和即次大堆最小标号出现的次数

代码:
这个代码,数组明显不会超过long long 自己把所有的int 全部替换成long long才过了。
 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll ans[100009];
struct ss
{
    ll v;
    ll pos;
}a[100009];
const bool com(const ss &a,const ss&b)
{
    if(a.v>b.v)return 1;
    else if(a.v==b.v)
    {
        return a.pos<b.pos;
    }
    return 0;
}
 int main()
{
    ll n;
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld",&a[i].v);
        a[i].pos=i;
    }
    sort(a+1,a+1+n,com);
    /*for(ll i=1;i<=n;i++)
    {
        cout<<a[i].v<<" "<<a[i].pos<<endl;
    }*/
    a[n+1].v=0;
    ll tmp=1;
    ll num=a[1].pos;
    for(ll i=2;i<=n+1;i++)
    {
        if(a[i].v==a[i-1].v)tmp++;
        else
        {
            ans[num]+=(a[i-1].v-a[i].v)*tmp;
            tmp++;
        }
        if(a[i].pos<num)
        {
            num=a[i].pos;
        }
    }
    for(ll i=1;i<=n;i++)
    {
       printf("%lld\n",ans[i]);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值