刷題記錄 CF每日一題打卡 2020.5月26-6月2

1.CF1198A MP3

題意有點繞
總需要的存儲空間爲nlog2tn*\log_{2} ttt爲不同音量的數量

現有的存儲空間爲 m8m*8

要選擇一個區間使所有的的音量值都變爲區間之內,使之可以儲存下來,最小的被更改的強度值的數量

先排序,並求出tt和每一個音量的數量,m8m*8

可以得出 log2tmn\log_{2} t\leq\frac{m}{n},我們需要找到一個符合條件的tt又要使被更改的強度值的數量最小,要怎麼辦呢?用雙指針,讓不同音量數量在maxxmaxx範圍內,並且記錄最多同時有多少個音量在隊列中,最終答案即爲nansn-ans

#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 - -

問最少要多少次操作能使其變爲迴文串

直接貪心,記錄下最左端需要修改的字母和最右端需要修改的字母

討論一下這樣的正確性,從下標00開始遍歷,達到的第一個需要改的即爲ll,最後一個修改的位置爲rr,最終光標移動的總次數爲

ans+=min(abs(p-r),abs(p-l));
ans+=max(r-l,0);

模擬一下就能明白是什麼意思

例如光標初始位置爲p=5p=5ll爲2,rr爲7,先加上757-5,即爲到r的距離,但是光標總是需要從l走到r這個位置的,所以需要加上rlr-l

對應位置的字母的改法就比較簡單了
完整代碼:

#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個數,使選出的數的和值最大

先求出前綴和

dp[i][j]dp[i][j]代表前ii個數選jj個區間可以獲得的最大值

轉移方程:dp[i][j]=max(dp[i][j],dp[im][j1]+sum[i]sum[im]);dp[i][j]=max(dp[i][j],dp[i-m][j-1]+sum[i]-sum[i-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

給出nn個已經選中的臺階

初始時有 nn 個平臺爲被選中,保證平臺 hh 被選中,您每次可以進行一個操作,不妨假設您當前站在平臺 xx 處(此時平臺 xx 一定被選中),即讓平臺 xx變成未被選中,而平臺 x1x - 1變成相反的狀態。

如果落差大於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

咕了,待補

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章