Atcoder 2335 Frequency 题解

Problem Statement

Snuke loves constructing integer sequences.

There are N piles of stones, numbered 1 through N. The pile numbered i consists of ai stones.

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

  1. Among the piles with the largest number of stones remaining, let x be the index of the pile with the smallest index. Append x to the end of s.
  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,…,N, how many times does it occur in the lexicographically smallest sequence?

Constraints

  • 1≤N≤105
  • 1≤ai≤109

Input

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

N
a1 a2  aN

Output

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

Sample Input 1

2
1 2

Sample Output 1

2
1

The lexicographically smallest sequence is constructed as follows:

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

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

Sample Input 2

10
1 2 1 3 2 4 2 5 8 1

Sample Output 2

10
7
0
4
0
3
0
2
3
0

按字典序排列,很容易想到贪心。将石堆按大小排列,每次拿出当前最大值,会发现有两种情况:

第一种情况

当次大值3的最左侧(记为y)的一个在最大值5最左侧(记为x)一个的左边时,会发现当把所有的5消成3时最优的情况x位总是最大的,所以x位的答案就为该值个数×(最大值-最小值),操作完后接下来的最大值就变成了j

第二种情况

当次大值3的最左侧(记为y)的一个在最大值5最左侧(记为x)一个的右边时,x位的答案与上面的情况相同,但操作完后的最大值任为x

在实际编写时,我们可以先将数组排序,从大到小操作,对于每个最大值记为f,找到其次大值t求出f位的答案。

  1. 如果为情况一,让f=t循环下去。
  2. 如果为情况二,f不变,让f(最大值)位的值变成次大值,方便接下去处理

    最后,一定要记得开long long,就因为这个挂了好几次

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,t=2,f=1;
     4 long long ans[100005];
     5 struct N{int data,num;}a[100005];
     6 bool comp(N x,N y){if(x.data==y.data) return x.num<y.num;else return x.data>y.data;}
     7 int main(){
     8     scanf("%d",&n);
     9     for(int i=1;i<=n;++i) scanf("%d",&a[i].data),a[i].num=i;
    10     sort(a+1,a+n+1,comp);
    11     while(t<=n){
    12         while(a[t].data==a[t-1].data) t++;
    13         ans[a[f].num]+=1ll*(a[f].data-a[t].data)*(t-1);
    14         if(a[t].num>a[f].num) a[f].data=a[t].data;
    15         else f=t;
    16         t++;
    17     }
    18     ans[a[f].num]+=1ll*a[f].data*n;
    19     for(int i=1;i<=n;++i) printf("%lld\n",ans[i]);
    20 }
    View Code

猜你喜欢

转载自www.cnblogs.com/xie-dodo/p/8965198.html