(银牌区)CCPC2018-湖南全国邀请赛 C. Just h-index HDU - 6278 主席树+二分

博客目录

原题 (吐槽一下题目描述非常绕口)

oj传送门

下面粘贴的格式不太好,参考pdf或者原题链接:

比赛题目: 
http://acm.hdu.edu.cn/downloads/2018ccpc_hn.pdf 
The hh-index of an author is the largest hh where he has at least hh papers with citations not less than hh. 

Bobo has published nn papers with citations a1,a2,…,ana1,a2,…,an respectively. 
One day, he raises qq questions. The ii-th question is described by two integers lili and riri, asking the hh-index of Bobo if has *only* published papers with citations ali,ali+1,…,ariali,ali+1,…,ari. 

Input

The input consists of several test cases and is terminated by end-of-file. 

The first line of each test case contains two integers nn and qq. 
The second line contains nn integers a1,a2,…,ana1,a2,…,an. 
The ii-th of last qq lines contains two integers lili and riri. 

Output

For each question, print an integer which denotes the answer. 

## Constraint 

* 1≤n,q≤1051≤n,q≤105 
* 1≤ai≤n1≤ai≤n 
* 1≤li≤ri≤n1≤li≤ri≤n 
* The sum of nn does not exceed 250,000250,000. 
* The sum of qq does not exceed 250,000250,000. 

Sample Input

5 3
1 5 3 2 1
1 3
2 4
1 5
5 1
1 2 3 4 5
1 5

Sample Output

2
2
2
3

题目大意:

在一个区间内求一个h,h满足区间内至少有h个数大于等于h

二分h(1到区间长度len),对于每个h检查是不是有h个大于等于它,也就是看看第h大是不是大于等于它 ,所以用主席树查询区间第k大的数

AC代码

#include <bits/stdc++.h>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=2e5+5e4+10;
const int M=maxn*100;
int n,q,m,tot;
int a[maxn],t[maxn];
int T[maxn],lson[M],rson[M],c[M];
void init_hs(){
    for(int i=1;i<=n;i++)
        t[i]=a[i];
    sort(t+1,t+1+n);
    m=unique(t+1,t+1+n)-t-1;
}
int build(int l,int r){
    int root = tot++;
    c[root]=0;
    if(l!=r){
        int mid=(l+r)>>1;
        lson[root]=build(l,mid);
        rson[root]=build(mid+1,r);
    }
    return root;
}
int hs(int x){
    return lower_bound(t+1,t+1+m,x)-t;
}
int update(int root ,int pos,int val){
    int newroot=tot++,tmp=newroot;
    c[newroot]=c[root]+val;
    int l=1,r=m;
    while(l<r){
        int mid=(l+r)>>1;
        if(pos<=mid){
            lson[newroot]=tot++;
            rson[newroot]=rson[root];
            newroot=lson[newroot];
            root=lson[root];
            r=mid;
        }
        else{
            rson[newroot]=tot++;
            lson[newroot]=lson[root];
            newroot=rson[newroot];
            root=rson[root];
            l=mid+1;
        }
        c[newroot]=c[root]+val;
    }
    return tmp;
}
int query(int left_root,int right_root,int k){
    int l=1,r=m;
    while(l<r){
        int mid=(l+r)>>1;
        if(c[lson[left_root]]-c[lson[right_root]]>=k){
            r=mid;
            left_root=lson[left_root];
            right_root=lson[right_root];
        }
        else{
            l=mid+1;
            k-=c[lson[left_root]]-c[lson[right_root]];
            left_root=rson[left_root];
            right_root=rson[right_root];
        }
    }
    return l;
}
inline int check(int num,int x){  
    if(num<=x){
        return 1;
    }else{
        return 0;
    }
}

int number[maxn];//元数据存档 
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("r.txt","r",stdin);
    #endif 
    while(scanf("%d%d",&n,&q)!=EOF){
        tot=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        init_hs();
        T[n+1]=build(1,m);
        for(int i=n;i;i--){
            int pos=hs(a[i]);
            T[i]=update(T[i+1],pos,1);
        }
        int tmp;
        while(q--){
            int x,y,l,r,mid;
            int t1,t2;
            scanf("%d%d",&x,&y);
            int len=y-x+1;
            l=1;
            r=len; //h只能在1到len之间。 
            while(l<r){
                mid=(l+r)>>1;
                t1=t[query(T[x],T[y+1],len-mid+1)];
                t2=t[query(T[x],T[y+1],len-(mid+1)+1)]; //二分h,对于每个h(mid)检查是不是有h个大于等于它,也就是看看第h大是不是大于等于它 
                if(check(mid,t1)){
                    if(check(mid+1,t2)){
                        l=mid+1;
                    }
                    else{
                        l=mid;
                        break;
                    }
                }else{
                    r=mid-1;
                }
            }
            printf("%d\n",l);
        }
    }
    return 0;
}

### CCPC 2023 H题 解析 关于CCPC 2023 H题的具体题目描述尚未公开,但从以往的比赛惯例以及类似的题目解析可以推测其可能涉及的内容和技术要点。以下是基于已有参考资料和专业知识对该类问题的解答框架。 #### 1. **问题背景** CCPC(Chinese Collegiate Programming Contest)作为国内重要的编程竞赛之一,通常会设计具有挑战性的算法问题来测试参赛者的逻辑思维能力和编码技巧。H题通常是比赛中的难点之一,往往涉及到复杂的算法模型或数据结构的应用[^2]。 #### 2. **潜在的技术方向** 根据过往的经验,H题可能会覆盖以下几个方面: - 动态规划 (Dynamic Programming)[^1] - 构造性问题 (Construction Problems)[^4] - 数学优化 (Mathematical Optimization) 假设该题属于动态规划类别,则需关注状态转移方程的设计;如果是构造性问题,则重点在于如何通过有限操作达到目标条件。 #### 3. **通用解题策略** 无论具体主题为何种类型,在面对高难度赛题时可遵循如下方法论: ##### (1)深入理解题目需求 仔细阅读并反复确认输入输出的要求及其约束条件,确保不会遗漏任何细节信息[^3]。 ##### (2)选取合适的算法工具箱 依据实际场景挑选最匹配的方法论,比如当存在重叠子问题且具备最优子结构性质时优先选用DP技术[^1]。 ##### (3)编写清晰易懂的代码实现 采用模块化的方式分步完成整个功能开发流程,并辅以充分注释说明每一部分的作用机制。 ```cpp // 示例伪代码片段展示基本框架布局 #include <bits/stdc++.h> using namespace std; int main(){ ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; // 输入规模参数 vector<long long> dp(n+1, INF); // 初始化dp数组,默认极值表示未访问过 dp[0]=0; for(int i=1;i<=n;i++){ for(auto &coin : coins){ if(i >= coin && dp[i - coin]+costs[coin]<dp[i]){ dp[i]=dp[i - coin]+costs[coin]; } } } cout << (dp[n]==INF ? -1 : dp[n])<< "\n"; } ``` 上述例子仅作示意用途,真实情况下应严格依照官方给定的数据范围调整变量类型及边界处理方式。 #### 4. **复杂度考量** 对于规模实例而言,效率至关重要。因此除了正确率之外还需兼顾运行时间和内存消耗指标。一般建议尽可能降低渐近时间开销至O(NlogN)甚至更低级别。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值