【牛客】小白月赛30部分题目题解(自我学习用)

https://ac.nowcoder.com/acm/contest/9667/F
知识点:贪心
我们首先要知道这题是怎么贪心的
首先我们看得出,除了最后一个拿不到,其他的每个元素都会拿到,也就是说价值都是会加到的
而我们贪心的方法就是每次都找最大的石头堆,然后让他和隔壁的合并,所以最后最大的石头堆会用到n-1次

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n; cin>>n;
    long long ans=0,m=0,x;
    for(int i=0;i<n;i++){
        cin>>x;
        m=max(x,m);
        ans+=x;
    }
    cout<<ans+m*(n-2);
    return 0;
}

——————————————————————————————————————————————————————————————————————————————————————

https://ac.nowcoder.com/acm/contest/9667/H
知识点:优先队列
这其实是一个利用优先队列维护数组的一个题目,
注意到题目只有两个操作,加数字和输出第k小的数字,并没有删除数字,因此我们只需要知道每次加入数字后第k小的数字是多少就行
用优先队列

#include <bits/stdc++.h>
using namespace std;
priority_queue<int>que;
int main(){
    ios::sync_with_stdio(false),cin.tie(0);
    int n,m,k; cin>>n>>m>>k;
    for(int i=0,x;i<n;i++){
        cin>>x; que.push(x);
        if(que.size()>k)que.pop();
    }
    while(m--){
        int x,y; cin>>x;
        if(x==1){
            cin>>y; que.push(y);
            if(que.size()>k)que.pop();
        }else{
            if(k>que.size())cout<<"-1\n";
            else {
                cout<<que.top()<<endl;
            }
        }
    }
    return 0;
}

————————————————————————————————————————————————————————————————————————————————————————

https://ac.nowcoder.com/acm/contest/9667/I
知识点:位运算
这里有一个知识点在,abb=a,就是这个
所以我们根据这个可以用前缀和预处理区间的异或和
可以直接再用一个数组来记录答案

#include <bits/stdc++.h>
using namespace std;
const int N=3030;
int a[N],b[N],c[N];
int main(){
    int n,m; cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)b[i]=b[i-1]^a[i];//前缀和
    for(int i=1;i<=n;i++){//长度为j的子序列最大异或和为c[j]
        for(int j=1;i+j-1<=n;j++){
            int x=b[i+j-1]^b[i-1];
            c[j]=max(c[j],x);
        }
    }
    for(int i=1;i<=n;i++)c[i]=max(c[i],c[i-1]);
    while(m--){
        int x; cin>>x;
        int ans=lower_bound(c+1,c+1+n,x)-c;//ans表示满足的最短的长度
        if(ans>=n+1)cout<<"-1\n";//越界
        else cout<<ans<<endl;
    }
    return 0;
}

————————————————————————————————————————————————————————————————————————————————————————————

https://ac.nowcoder.com/acm/contest/9667/J
知识点:动态规划
我是万万没想到这个用dp写这么简单,毕竟我想了半天贪心
不过贪心就是一种特殊的dp
不过代码还是比较好理解的,直接看注释就行

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
ll a[N],dp[N];
int main(){
    int n; cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        dp[a[i]]++;
    }
    dp[0]=0;
    for(int i=1;i<=N;i++){
        dp[i]*=i;//将当前dp值转换为分数
        dp[i]=max(dp[i-1],dp[i-2]+dp[i]);//看取自己还是隔壁俩
    }
    cout<<dp[N-1];
    return 0;
}
posted @ 2020-12-08 16:50  Time_Limit_Exceeded  阅读(111)  评论(0编辑  收藏  举报