Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final) (A B C D)

FXH_Violet發表於2020-11-03

昨天打了一場Div 2,做了三題吧,賽後補了D,前四題都是思維題沒什麼演算法,賽後跟群友討論了下思路,感覺自己的方法都比較笨吧,再來梳理梳理思路,(其實總感覺自己打cf以及atcoder有的時候是亂搞出來的,自己不能給別人講的很明白,還是慢慢練吧…畢竟自己思維一直不好)

A題

題解:感覺算是一個性質吧,就是如果我們找到一個n>=2的數,從這個數到2*n-2,這些數全部都是不能互相除盡的。

程式碼

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n,m;
int a,b;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=n*2;i<=4*n-2;i+=2)
		{
			if(i==2*n) cout<<i;
			else cout<<' '<<i;
		}
		cout<<endl;
	}
}

B題

思路:其實就是遍歷字串,如果是第一個1,那麼它沒有選擇只能選擇引爆,如果是之後的1,它有兩種選擇,一種是直接引爆,另一種是把它和前面一個1之間的零全部填上炸彈,然後取這兩種的最小費用就可以了。

程式碼

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n,m;
int a,b;
int s[N];
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>a>>b;
		string s;
		cin>>s;
		int z=-10;
		int idx=0;
		long long ans=0;
		for(int i=0;i<s.size();i++)
		{
			if(s[i]=='1')
			{
				if(z<0) 
				{
				z=i;
				ans+=a;	
				}
				else
				{
					ans+=min(a,b*(i-z-1));
					z=i;
				}
			}
		}
		
		cout<<ans<<endl;
	}
}

C題

思路:C題就是我感覺跟大佬有差距的地方了,我用的真的是特別樸素的模擬,然而賽後其他很多人都是用的二分查詢以及二分答案做出來的,據說這道題可以不用sort,那樣的話演算法複雜度會降低很多;其實就是說如果你用到sort,那麼這道題複雜度一定是nlongn的,那樣子你用模擬和二分對複雜度都是沒影響的,但如果不用排序的話複雜度就會低了。我的思路就是用一個結構體存起來兩個時間,然後按照快遞的時間從大到小排序,因為我們最大時間取決於我們快遞時間最長以及自己去取的時間,因而我們只要一直增大自己取的時間,減少最大快遞時間,即可得到最短時間

程式碼

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
ll t,n,m;
ll a[N],b[N];
struct node{
	ll x;
	ll y;
}nodes[N];
bool cmp(node h,node j)
{
	if(h.x==j.x)
	return h.y<j.y;
	else
	{
		return h.x>j.x;
	}
}
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		for(int i=1;i<=n;i++)
		{
			cin>>b[i];
		}
		for(int i=1;i<=n;i++)
		{
			nodes[i]={a[i],b[i]};
		}
		sort(nodes+1,nodes+1+n,cmp);
		ll ans=nodes[1].x;
		ll res=0;
		nodes[n+1].x=0;
		for(int i=1;i<=n;i++)
		{
			res+=nodes[i].y;
			if(res<=nodes[i+1].x)
			{
				ans=nodes[i+1].x;
			}
			else break;
		}
		cout<<min(res,ans)<<endl;
	}
}

D題

思路:比賽的時候想的是按照對稱性,外層兩個數的和要大於內層兩個數的和,然後wa了,賽後看了別人的想法,明白了這只是充分條件,什麼意思?也就是不滿足這個條件也有能成立的,然後看了群友的想法:遍歷陣列,如果當前的數比下一個數大,就沒問題,因為此時下一位數只需要從前面減就能減到0,而噹噹前數小於下一位時,那麼下一位數就需要有一部分從後面減才行,此時我們用一個變數加上此時需要從後面減的值,即:a[i+1]-a[i],而後面的每一位都要大於這個變數,因為從後面減時他們也要被減,這樣迴圈下來,如果整個陣列都滿足就能全都減為0了。

程式碼

#include<bits/stdc++.h>
using namespace std;
const int N=30005;
typedef long long ll;
ll s[N];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>s[i];
		}
		ll ans=0;
		bool jud=true;
		for(int i=1;i<=n-1;i++)
		{
			if(ans>s[i]) 
			{
				jud=false;
				break;
			}
			if(s[i+1]>s[i]) ans+=s[i+1]-s[i];
		}
		if(s[n]<ans) jud=false;
		if(jud) cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	 } 
}

相關文章