- CF1198A MP3
- CF486C Palindrome Transformation
- CF467C George and Job
- CF1228C Primes and Multiplication
- CF1279C Stack of Presents
- CF1238C Standard Free2play
- CF1223C Save the Nature
1.CF1198A MP3
題意有點繞
總需要的存儲空間爲,爲不同音量的數量
現有的存儲空間爲
要選擇一個區間使所有的的音量值都變爲區間之內,使之可以儲存下來,最小的被更改的強度值的數量
先排序,並求出和每一個音量的數量,
可以得出 ,我們需要找到一個符合條件的又要使被更改的強度值的數量最小,要怎麼辦呢?用雙指針,讓不同音量數量在範圍內,並且記錄最多同時有多少個音量在隊列中,最終答案即爲
#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans,c,maxx;
void fuck();
inline int read()
{
int x=0,k=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
int a[400005],b[400005];
bool cmp(int x,int y){
return x>y;
}
vector<int>v;
signed main(){
cin>>n>>m;
m*=8;
for(int i=1;i<=n;i++){
a[i]=read();
}
sort(a+1,a+1+n,cmp);
int num=0;
int t=1;
for(int i=1;i<=n;i++){
if(a[i]!=a[i-1]){
num++;
b[t]=num;
t++;
num=0;
}
else num++;
}
maxx=m/n;
if(log2(t)<=maxx){
cout<<"0";
return 0;
}
maxx=pow(2,maxx);
// for(int i=1;i<=t+maxx;i++){
// b[i]+=b[i-1];
// }
ans=0;
queue<int>q;
for(int i=1;i<=t;i++){
q.push(b[i]);
c+=b[i];
if(q.size()>maxx){
int x=q.front();
c-=x;
q.pop();
}
ans=max(ans,c);
}
cout<<n-ans;
}
2.CF486C Palindrome Transformation
有四種操作,光標左移,右移,將光標所在的字母++ or - -
問最少要多少次操作能使其變爲迴文串
直接貪心,記錄下最左端需要修改的字母和最右端需要修改的字母
討論一下這樣的正確性,從下標開始遍歷,達到的第一個需要改的即爲,最後一個修改的位置爲,最終光標移動的總次數爲
ans+=min(abs(p-r),abs(p-l));
ans+=max(r-l,0);
模擬一下就能明白是什麼意思
例如光標初始位置爲,爲2,爲7,先加上,即爲到r的距離,但是光標總是需要從l走到r這個位置的,所以需要加上
對應位置的字母的改法就比較簡單了
完整代碼:
#include<bits/stdc++.h>
using namespace std;
string a;
int n,p,l=-1,r;
int main(){
cin>>n>>p;
cin>>a;
n--;
p--;
long long ans=0;
if(p>n/2)p=n-p;
for(int i=0;i<=n/2;i++){
if(a[i]!=a[n-i]){
int s=abs(a[i]-a[n-i]);
ans+=min(s,26-s);
if(l<0)l=i;
else r=i;
}
}
ans+=min(abs(p-r),abs(p-l));
ans+=max(r-l,0);
if(l<0)cout<<"0";
else cout<<ans;
}
3.CF467C George and Job
n個數,選出k組,每組m個數,使選出的數的和值最大
先求出前綴和
代表前個數選個區間可以獲得的最大值
轉移方程:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
int x=0,k=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*k;
}
int n,m,k;
int a[5005],sum[5005],dp[5005][5005];
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
a[i]=read();
sum[i]=a[i];
}
for(int i=1;i<=n;i++){
sum[i]+=sum[i-1];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
dp[i][j]=dp[i-1][j];
if(i>=m){
dp[i][j]=max(dp[i][j],dp[i-m][j-1]+sum[i]-sum[i-m]);
}
}
}
cout<<dp[n][k];
return 0;
}
4.CF1228C Primes and Multiplication
數論,咕咕咕
5.CF1279C Stack of Presents
放回來的時候可以任意順序,維護最大深度即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int tt,n,m,a[maxn],b[maxn],num[maxn];
int main(){
cin>>tt;
while(tt--){
long long ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;
cin>>x;
a[x]=i;
}
int dep=0;
for(int i=1;i<=m;i++){
int x;
cin>>x;
if(a[x]>dep){
ans+=(a[x]-i)*2+1;
dep=a[x];
}
else ans++;
}
cout<<ans<<endl;
}
return 0;
}
6.CF1238C Standard Free2play
給出個已經選中的臺階
初始時有 個平臺爲被選中,保證平臺 被選中,您每次可以進行一個操作,不妨假設您當前站在平臺 處(此時平臺 一定被選中),即讓平臺 變成未被選中,而平臺 變成相反的狀態。
如果落差大於1,不管這個數字是多少都是一樣的,需要一個魔法水晶
比如選中在1000,999和1是打開的,關閉1000的時候999也會關閉,用水晶關閉999這一層才能到達999,然後關閉999,998變爲打開狀態,關閉998,997又變成打開
#include<bits/stdc++.h>
using namespace std;
int t,h,n,a[200005];
int main(){
cin>>t;
while(t--){
cin>>h>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int ans=0;
a[n+1]=0;
for(int i=2;i<=n+1;i++){
if(a[i]-a[i+1]>1)ans++;
else i++;
}
cout<<ans<<endl;
}
return 0;
}
7.CF1223C Save the Nature
咕了,待補