1. 程式人生 > 其它 >acwing 3745. 牛的學術圈 I(構造)

acwing 3745. 牛的學術圈 I(構造)

目錄

題目傳送門

題目描述

由於對電腦科學的熱愛,以及有朝一日成為 「Bessie 博士」的誘惑,奶牛 Bessie 開始攻讀電腦科學博士學位。

經過一段時間的學術研究,她已經發表了 NN 篇論文,並且她的第 ii 篇論文得到了來自其他研究文獻的 cici 次引用。

Bessie 聽說學術成就可以用 hh 指數來衡量。

hh 指數等於使得研究員有至少 hh 篇引用次數不少於 hh 的論文的最大整數 hh。

例如,如果一名研究員有 44 篇論文,引用次數分別為 (1,100,2,3)(1,100,2,3),則 hh 指數為 22,然而若引用次數為 (1,100,3,3)(1,100,3,3) 則 hh 指數將會是 33。

為了提升她的 hh 指數,Bessie 計劃寫一篇綜述,並引用一些她曾經寫過的論文。

由於頁數限制,她至多可以在這篇綜述中引用 LL 篇論文,並且她只能引用每篇她的論文至多一次。

請幫助 Bessie 求出在寫完這篇綜述後她可以達到的最大 hh 指數。

注意 Bessie 的導師可能會告知她純粹為了提升 hh 指數而寫綜述存在違反學術道德的嫌疑;我們不建議其他學者模仿 Bessie 的行為。

輸入格式

輸入的第一行包含 NN 和 LL。

第二行包含 NN 個空格分隔的整數 c1,…,cNc1,…,cN。

輸出格式

輸出寫完綜述後 Bessie 可以達到的最大 hh 指數。

資料範圍

1≤N≤1051≤N≤105,
0≤ci≤1050≤ci≤105,
0≤L≤1050≤L≤105

輸入樣例1:

4 0
1 100 2 3

輸出樣例1:

2

樣例1解釋

Bessie 不能引用任何她曾經寫過的論文。上文中提到,(1,100,2,3) 的 h 指數為 2。

輸入樣例2:

4 1
1 100 2 3

輸出樣例2:

3

如果 Bessie 引用她的第三篇論文,引用數會變為 (1,100,3,3)。上文中提到,這一引用數的 h 指數為 3

構造

分析

思想:

  • 將陣列從大到小排序後,我們可以根據下標確定有多少篇引用量>=下標對應引用量: 如100 3 2 1 即 1篇>=100,2篇>=3,3篇>=2,4篇>=1 。
  • 確定邊界值(有可能優化h指數的地方):邊界值即 下標>下標對應引用量的第一個位置。如100 3 2 1 為i=3和100 3 3 1 為i=4。
  • 其次,我們需要確定Bessie自己寫的綜述產生的引用量(僅能對多個+1),加在哪一部分利於提高h指數。
  • 可以發現,提高h指數,實質是:將邊界值+1以靠近下標 3篇>=2 ,而將1往邊界值後的小引用量加是沒有作用的(小引用量和下標的差距一定>=2),所以如果有多餘的L,應該往邊界值前的大引用量+1。
    重新排序後,尋找邊界值,即為答案。

作者:Lg_970
連結:https://www.acwing.com/solution/content/101186/
來源:AcWing
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

程式碼

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int n, l; 
int c[N];

bool cmp(int a, int b)
{
    return a > b;
}

int main()
{
    int tmp;
    int ans = 0;
    scanf("%d%d", &n, &l);
    for(int i = 1; i <= n; i++)  scanf("%d", &c[i]);
    
    sort(c+1, c+n+1, cmp);
    
    for(int i = 1; i <= n; i++)
    {
        if(i > c[i])
        {
          tmp = i;
          break;  
        } 
    }
    
    // 每個文獻只能引用一次
    for(int i = tmp; i >= 1; i--)
    {
        if(l) c[i]++, l--;
    }
    
    sort(c+1, c+n+1, cmp);
    for(int i = n; i >= 1; i--)
    {
        if(i <= c[i]) 
        {
            ans = i;
            break;
        }
        
    }
    
    printf("%d\n", ans);
    return 0;
}

時間複雜度

參考文章