C. Game of Mathletes
题意:一个数组 alice和bob依次选数,若他们选的数的和为k则得分+1,alice想最小化得分,bob最大得分
算法:模拟
思路:最终的数对是由bob决定的 alice的决定并不影响结果,统计数组中相加为k的数对即可
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int Q = 2e5 + 9;
const ll MOD = 1e9 + 7;
ll a[Q];map<ll,ll> mp;
void solve(){
ll n,k;cin>>n>>k;mp.clear();
for (ll i = 1; i <= n; i++)
{
cin>>a[i];mp[a[i]]++;
}
ll ans=0;ll sum=0,top=0;
for (ll i = 1; i <= n; i++)
{
if(top>=n-sum) break;
if(mp[a[i]]==0) continue;
mp[a[i]]--;sum++;
if(mp[k-a[i]]>0){
ans+=1;
mp[k-a[i]]--;
sum++;
}else{
top++;
top%=2;
}
}
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _ = 1;cin>>_;
while(_--){
solve();
}
return 0;
}
D. Subtract Min Sort
题意:给定一个数组,你可以对相邻两个元素依次减去他们的小值,是否可以变成不递减的数组(单调递增)
算法:模拟
思路:从第一个位置开始 在每个位置上都进行这个操作,然后检查是否符合条件。
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int Q = 2e5 + 9;
const ll MOD = 1e9 + 7;
ll a[Q];
void solve(){
ll n;cin>>n;
for (ll i = 1; i <= n; i++)
{
cin>>a[i];
}
for (ll i = 1; i < n; i++)
{
ll now=min(a[i],a[i+1]);
a[i]-=now;
a[i+1]-=now;
}
for (ll i = 1; i <= n; i++)
{
// cout<<a[i]<<" ";
}
for (ll i = 1; i < n; i++)
{
if(a[i+1]<a[i]) {
cout<<"NO\n";
return;
}
}
cout<<"YES\n";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _ = 1;cin>>_;
while(_--){
solve();
}
return 0;
}
E. Graph Composition
题意:两张无向图 F和G 可以删除或添加F图的边,使得F中任意两点u和v 可以通过u到达v,则G中也能,若这两点不能 则G也不能
算法:并查集
思路:先使用并查集建立多个连通块G
①删除部分、查询F中的每一条边的两边是否在G中连接,若不连接则删除且ans+1,若连接则使用并查集建立这条边。
②添加部分、查询G中的每一条边是否在F中连接,若不连接则连接两边,用并查集建立该边且ans+1。
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int Q = 2e5 + 9;
const ll MOD = 1e9 + 7;
ll b[Q],c[Q];
int root(int x)//查询G图是否联通
{
if(b[x] == x) return x;
return b[x] = root(b[x]);
}
int root2(int x) //查询F图是否联通
{
if(c[x] == x) return x;
return c[x] = root2(c[x]);
}
vector<pair<ll,ll>> a,a2;//a是F图存的边 a2是G图存的边
void solve(){
ll n,m1,m2;cin>>n>>m1>>m2;
a.clear();a2.clear();
for (ll i = 1; i <= n; i++) b[i]=i,c[i]=i;//初始化
for (ll i = 0; i < m1; i++)
{
ll o,p;cin>>o>>p;
a.push_back({o,p});
}
for (ll i = 0; i < m2; i++)
{
ll o,p;cin>>o>>p;
a2.push_back({o,p});
b[root(o)]=root(p);//建立G图并查集
}
ll ans=0;
for (ll i = 0; i < m1; i++)
{
ll o,p;o=a[i].first;p=a[i].second;//F图的两点
if(root(o)!=root(p)) ans++;//F图的o p两点在G不连通 则删除该边(不建立该边) 花费+1
else c[root2(o)]=root2(p);//若联通则 保留并建立该边
}
for (ll i = 0; i < m2; i++)
{
ll o,p;o=a2[i].first;p=a2[i].second;
if(root2(o)!=root2(p)) {//G图的o p两点在F不连通 则建立该边 花费+1
ans++;
c[root2(o)]=root2(p);
}
}
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _ = 1;cin>>_;
while(_--){
solve();
}
return 0;
}