Educational Codeforces Round 93 (Rated for Div. 2)A-B-C-D

比赛链接:Educational Codeforces Round 93 (Rated for Div. 2)

文章目录

    • A.Bad Triangle 思维
    • B.Substring Removal Game 思维
    • C. Good Subarrays 预处理+前缀和
    • D. Colored Rectangles 三维dp

A.Bad Triangle 思维

题意:n个数从小到大,是否可以挑出三个数不能构成三角形,输出这个三个数的下标,否则输出-1

#pragma GCC optimize(2)
#include 
using namespace std;
#define endl "\n"
int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);
  int _;cin>>_;
  while(_--){
  	int n,f=0;cin>>n;
  	vector<int>a(n,0);
  	for(int i=0;i<n;i++)cin>>a[i];
  	if(a[0]+a[1]<=a[n-1])f=1;
  	if(f)cout<<1<<" "<<2<<" "<<n<<endl;
  	else cout<<-1<<endl;
  }
   return 0;
} 

B.Substring Removal Game 思维

题意:在01字符串中,两个人每次轮流挑出连续1的子串,两个人都想贪心获得更多的1,问先手的人最多可以获得多少个1
题意:先预处理统计连续1的次数,sort排序后,取奇数位的和。

#pragma GCC optimize(2)
#include 
using namespace std;
#define ll long long
#define endl "\n"
int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);
  int _;cin>>_;
  while(_--){
  	string s;cin>>s;
  	vector<int>a;
  	int n=s.size(),l=0;
  	for(int i=0;i<n;i++){
  		if(s[i]=='1')l++;
  		else if(s[i]=='0'){
  			if(l>=1)a.push_back(l);
			  l=0;	
		}
	}
	if(l!=0)a.push_back(l);
  	sort(a.begin(),a.end());
  	reverse(a.begin(),a.end());
  	ll ans=0;
  	for(int i=0;i<a.size();i+=2)ans+=a[i];
  	cout<<ans<<endl;
  }
   return 0;
} 

C. Good Subarrays 预处理+前缀和

题意:在长度为n的数组a[]中,求 ∑ i = l r a i = r − l + 1 \sum^r_{i=l}a_i=r-l+1 i=lrai=rl+1种类的个数
题解:字符串输出,预处理成数组,再对该数组每个数都进行减一操作后,再对该数组进行前缀和处理, O ( n ) O(n) O(n)for一遍前缀和,ans等于该前缀和之前出现的次数(预处理-1后的前缀和,0本身就符合直接加一次)并用map统计该前缀和出现的次数。

这道题真的离谱,只能说cf的评测机真的快,加上
#pragma GCC optimize(“Ofast”)
#pragma GCC target(“avx,avx2,fma”)

O ( n 2 ) O(n^2) O(n2)的hack不了,放过了。

#pragma GCC optimize(2)
#include 
using namespace std;
#define ll long long
#define endl "\n"
const int MAX=1e6+7;
int change(char x){
	return int(x-'0');
}
ll a[MAX],b[MAX];
int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);
  int _;cin>>_;
  while(_--){
  	int n;cin>>n;
  	string s;cin>>s;
  	ll ans=0,l=0,r=0,sum=0;
  	map<ll,ll>mp;
  	for(int i=1;i<=n;i++)a[i]=change(s[i-1])-1;	
	for(int i=1;i<=n;i++)b[i]=b[i-1]+a[i];
  	for(int i=1;i<=n;i++){
  		if(b[i]==0)ans++;
		if(mp[b[i]])ans+=mp[b[i]];
		mp[b[i]]++;
	}
	cout<<ans<<endl;
  }
   return 0;
} 

D. Colored Rectangles 三维dp

题意:有R,G,B三种颜色的棍子,每个中棍子都r,g,b个,每个棍子的长度独立输入的,每次可以需要取两个不同颜色的棍子组成矩形,可以组成多个矩形,问最后这些矩形面积和最大值是多少。
题解:先每个组内大到小排个序,记个 f[i][j][k] 表示第一组考虑前 i 个,第二组考虑前 j 个,第三组考虑前 k 个的最大值,转移比较显然,需要注意的是for是从0开始的。

#pragma GCC optimize(2)
#include 
using namespace std;
#define ll long long
#define endl "\n"
const int MAX=1e6+7;
ll f[205][205][205];
int main(){
    ios_base::sync_with_stdio(0);cin.tie(0);
   int r,g,b;cin>>r>>g>>b;
   vector<ll>R(r+1,0),G(g+1,0),B(b+1,0);
   for(int i=1;i<=r;i++)cin>>R[i];
   for(int i=1;i<=g;i++)cin>>G[i];
   for(int i=1;i<=b;i++)cin>>B[i];
   sort(R.begin()+1,R.end());reverse(R.begin()+1,R.end());
   sort(G.begin()+1,G.end());reverse(G.begin()+1,G.end());
   sort(B.begin()+1,B.end());reverse(B.begin()+1,B.end());
   ll ans=0;
   for(int i=0;i<=r;i++){
   		for(int j=0;j<=g;j++){
   			for(int k=0;k<=b;k++){
   				if(i!=0&&j!=0)
   				f[i][j][k]=max(f[i][j][k],f[i-1][j-1][k]+R[i]*G[j]);
   				if(j!=0&&k!=0)
   				f[i][j][k]=max(f[i][j][k],f[i][j-1][k-1]+G[j]*B[k]);
   				if(i!=0&&k!=0)
   				f[i][j][k]=max(f[i][j][k],f[i-1][j][k-1]+R[i]*B[k]);
				ans=max(ans,f[i][j][k]);
			}	
		}
   }
   cout<<ans;
   return 0;
} 

你可能感兴趣的:(codeforces题解)