B. Subsequence Update
链接:Problem - B - Codeforces
题意:给定一个数组 可以选择任意个元素 后对这些元素进行排序 问你给定一个区间 这个区间的最小值
算法:贪心 排序
思路:下标1到r的最小个(r-l+1)元素 或者 下标l到n的最小个(r-l+1)元素
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int Q = 1e5 + 9;
const ll MOD = 1e9 + 7;
ll a[Q],b[Q];
void solve(){
ll n,l,r;cin>>n>>l>>r;
for (ll i = 1; i <= n; i++)
{
cin>>a[i];b[i]=a[i];
}
sort(a+1,a+1+r);
sort(b+l,b+1+n);
ll ans=0,ans2=0;
for (ll i = 1; i <= r-l+1; i++)
{
ans+=a[i];
}
for (ll i = l; i <= r; i++)
{
ans2+=b[i];
}
cout<<min(ans,ans2)<<"\n";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _ = 1;cin>>_;
while(_--){
solve();
}
return 0;
}
C. Remove Exactly Two
链接:Problem - C - Codeforces
题意:给出一个树 删除两个节点 最多有多少个联通块
算法:贪心
思路:将节点 先按度排序 再按相邻节点与自己度相同的个数排序 删除最大的两个即可,为什么?因为若当前有四个度为3的节点 删除第一个后 将其他三个节点的度数减少了一个 导致第二次删除的度数只能为2
此图先删除1和先删除2 3 4的结果不同
代码:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int Q = 2e5 + 9;
const ll MOD = 1e9 + 7;
set<ll> d[Q];
bool vis[Q];
ll t[Q];
struct cmp
{
bool operator()(pair<pair<ll,ll>,ll> l,pair<pair<ll,ll>,ll> r){
if(l.first.first==r.first.first) return l.first.second>r.first.second;
return l.first.first<r.first.first;
}
};
void solve(){
ll n;cin>>n;
ll ans=1;
for (ll i = 1; i <= n; i++) d[i].clear(),vis[i]=false,t[i]=0;
for (ll i = 1; i < n; i++)
{
ll o,p;cin>>o>>p;
d[o].insert(p);
d[p].insert(o);
}
priority_queue<pair<pair<ll,ll>,ll>,vector<pair<pair<ll,ll>,ll>>,cmp> pq;
for (ll i = 1; i <= n; i++){
for(auto j:d[i]){
if(d[j].size()==d[i].size()) t[i]++;
}
pq.push({
{d[i].size(),t[i]},i});
}
auto o=pq.top();
while(pq.size())pq.pop();
ans+=o.first.first-1;
for(auto i:d[o.second]){
d[i].erase(o.second);
}
for (ll i = 1; i <= n; i++) t[i]=0;
for (ll i = 1; i <= n; i++){
if(i==o.second) continue;
for(auto j:d[i]){
if(d[j].size()==d[i].size()) t[i]++;
}
pq.push({
{d[i].size(),t[i]},i});
}
ans+=pq.top().first.first-1;
cout<<ans<<"\n";
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
ll _ = 1;cin>>_;
while(_--){
solve();
}
return 0;
}