【牛客】小白月賽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;
}