比赛链接:Dashboard - Codeforces Global Round 24 - Codeforces
A: 贪心
题意:给定一个长度为 n 的序列,定义一段序列的价值为序列长度减去序列内出现的数的种类。求一个序列内价值最大的一个子序列。
分析:我们发现,ans=len(长度)-m(种类),种类数是随着区间长度非降的,那么最优的情况,一定是长度为n的时候。max=n-m。
代码:
#include<bits/stdc++.h>
#define all(v) v.begin(),v.end()
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
typedef pair<int,int>PII;
int a[N];
inline void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
cout<<1<<" "<<n<<"\n";
}
signed main(){
int T;cin>>T;
while(T--) solve();
}
B:结论
题意:给定一个大小为 n 的集合,每次可以选取两个不同的数,将两个数的差放入集合内,集合内不允许出现重复元素,求集合内最多出现多少个元素
分析:通过手撸样例会发现,给定两个数a,b。如果gcd(a,b)=1,则一定能够构造出1-max(a,b)。
先求出集合的gcd。
如果gcd=1,则ans=max(集合)。
如果gcd!=1,则ans=max/gcd(结论)
代码:
#include<bits/stdc++.h>
#define all(v) v.begin(),v.end()
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
typedef pair<int,int>PII;
int a[N];
inline void solve(){
int n;cin>>n;
int maxx=0;
for(int i=1;i<=n;i++) cin>>a[i],maxx=max(maxx,a[i]);
int gcd=a[1];
for(int i=2;i<=n;i++){
gcd=__gcd(gcd,a[i]);
}
cout<<maxx/gcd<<"\n";
}
signed main(){
int T;cin>>T;
while(T--) solve();
}
C:贪心+构造
题意:给定n个带权点,在点中添加若干条无向边,使得不存在连续递增的路径。(连续递增指的是存在一条路径,经过的点权非下降的长度大于等于 2 ),请问最多添加多少条边。
ps:思路来自:Codeforces Global Round 24(A-D) - 知乎
分析:
代码:
#include<bits/stdc++.h>
#define all(v) v.begin(),v.end()
#define int long long
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int N=2e5+10;
typedef pair<int,int>PII;
int a[N];
inline void solve(){
int n;cin>>n;
int maxx=0;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+1+n);
vector<int>v;
int cur=a[1],cnt=0;
for(int i=1;i<=n;i++){//将相同的数分为一组
if(cur==a[i]) cnt++;//cnt用于记录元素个数
else{
v.push_back(cnt);
cur=a[i];cnt=1;
}
}
v.push_back(cnt);//最后漏了一个a[n]
if(a[1]==a[n]) cout<<n/2<<"\n";
else{
int ans=0,m=0;
for(auto x:v){
m+=x;//统计一个组的元素个数
ans=max(ans,m*(n-m));
}
cout<<ans<<"\n";
}
}
signed main(){
int T;cin>>T;
while(T--) solve();
}