Codeforces Round #661 (Div. 3) A~E1
原作者為 DOEMsy@cnblogs, 本作品采用 CC 4.0 BY 進行許可,轉載請注明出處,
上分場找回了點自信,

https://codeforces.com/contest/1399
A. Remove Smallest
題意
給定一個陣列 \(a_1,a_2,...,a_n\) ,每次操作可以選取陣列中兩個相差不大于 \(1\) 的數字,洗掉其中一個,
詢問能否刪到最后剩余一個數字,
解題
保證陣列有序后,相鄰元素差值不超過 \(1\) 即可,
#include<bits/stdc++.h>
//#include<windows.h>
#define ll long long
#define fr(i,n) for(ll i=0;i<n;i++)
using namespace std;
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
int a[55];
fr(i,n) cin>>a[i];
sort(a,a+n);
int p = 1;
fr(i,n-1){
if(a[i+1]-a[i]>1) p++;
}
//cout<<1<<endl;
if(p>1) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
B. Gifts Fixing
題意
有 \(n\) 個禮物,每個禮物由 \(a_i\) 個糖果和 \(b_i\) 個橘子組成,
每次可以對一個禮物進行以下操作:
- 吃掉一個糖果;
- 吃掉一個橘子;
- 吃掉一個糖果和一個橘子,
詢問最少多少次操作可以使得所有禮物的糖果和橘子都相同,
解題
簡單貪心,將所有的糖果和橘子變成分別變成最少的數量,每一堆的最少花費為 \(max(a_i-a_{min},b_i-b_{min})\) ,求和即可,
#include<bits/stdc++.h>
//#include<windows.h>
#define ll long long
#define fr(i,n) for(ll i=0;i<n;i++)
using namespace std;
int main(){
int t;cin>>t;
while(t--){
ll a[55],b[55];
int n;cin>>n;
fr(i,n) cin>>a[i];
fr(i,n) cin>>b[i];
ll mina = *min_element(a,a+n);
ll minb = *min_element(b,b+n);
ll ans = 0;
fr(i,n){
ans+=max(a[i]-mina,b[i]-minb);
}
cout<<ans<<endl;
}
return 0;
}
C. Boats Competition
題面
有一群人,戰斗力為 \(w_1,w_2,...,w_n\) ,要求兩兩組隊,且每個隊伍的戰斗力必須相同,
詢問最多可以組成多少個隊伍,
解題
由于人數和戰斗力范圍較小,可以直接在 \([2,2n]\) 內遍歷隊伍戰斗力范圍,取組成數量最多值,復雜度 \(O(2n^2)\),
#include<bits/stdc++.h>
//#include<windows.h>
#define ll long long
#define fr(i,n) for(ll i=0;i<n;i++)
#define memset0(dp) memset(dp,0,sizeof(dp))
using namespace std;
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
int a[550];memset0(a);
fr(i,n){
int inp;cin>>inp;
a[inp]++;
}
int maxs = 0,maxnum = 0;
frr(s,2,2*n+1){
int num = 0;
frr(i,1,n+1){
if(s-i>0) num+=min(a[i],a[s-i]);
}
num/=2;
maxnum = max(num,maxnum);
}
cout<<maxnum<<endl;
}
return 0;
}
D. Binary String To Subsequences
題意
給定一個由 \(01\) 組成的字串 \(S\),問最少分成多少個子串,使得每個子串 \(01\) 交錯,
并且輸出每一個字符被分配到的子串編號,
解題
注意題中說的是子串,不是連續子串,
類似 \(dp\) 的思路,將前面的所有子串狀態存盤,對于當前字符 \(S_i\) 有:
- 如果存在結尾與 \(S_i\) 不同的子串,則可以用 \(S_i\) 續接該子串,
- 否者用 \(S_i\) 新建一個子串,
關于子串的存盤只需要記錄結尾和編號即可,復雜度 \(O(n)\) ,
#include<bits/stdc++.h>
//#include<windows.h>
#define ll long long
#define fr(i,n) for(ll i=0;i<n;i++)
#define frs(i,n,flag) for(ll i=0;i<n&&flag;i++)
#define e5 100005
#define print_arr(begin,end) for(auto it = begin;it!=end;it++) cout<<*it<<" "; cout<<endl;
using namespace std;
int a[2*e5];
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
string inp;cin>>inp;
int maxsz = 0;
//fr(i,n) a[i] = 0;
stack<int>ct[2];
fr(i,n){
if(!ct[!(inp[i]-'0')].empty()){
a[i] = ct[!(inp[i]-'0')].top();
ct[!(inp[i]-'0')].pop();
ct[(inp[i]-'0')].push(a[i]);
}else{
ct[(inp[i]-'0')].push(++maxsz);
a[i] = maxsz;
}
}
cout<<maxsz<<endl;
print_arr(a,a+n);
}
return 0;
}
E1. Weights Division (easy version)
題意
給定一棵帶邊權的樹,每次操作可以選擇一條邊,使其權值 \(w_i = \lfloor\frac{w_i}{2}\rfloor\) ,
詢問至少多少次操作,可以使得葉節點到根部的路徑權總和小于等于 \(S\) ,
解題
貪心,選取一個邊會對權值和產生的影響為 \((w_i-\lfloor\frac{w_i}{2}\rfloor)*cnt\) ,\(cnt\) 為經過該邊的葉節點數量,優先選取影響大的,
先 \(dfs\) 跑出每一條邊的 \(w_i,cnt\),再以單調佇列維護,不斷操作,直到和小于等于 \(S\) ,
復雜度 \(O(nlogn)\) ,
#include<bits/stdc++.h>
//#include<windows.h>
#define ll long long
#define fr(i,n) for(ll i=0;i<n;i++)
#define frs(i,n,flag) for(ll i=0;i<n&&flag;i++)
#define frr(i,j,n) for(ll i=j;i<n;i++)
#define r_frr(i,j,n) for(ll i=n-1;i>=j;i--)
#define frrs(i,j,n,flag) for(ll i=j;i<n&&flag;i++)
#define r_frrs(i,j,n,flag) for(ll i=n-1;i>=j&&flag;i--)
#define yes "yes"
#define no "no"
#define memset0(dp) memset(dp,0,sizeof(dp))
#define min_get(a,b) a = min(a,b)
#define max_get(a,b) a = max(a,b)
#define PI 3.14159265354
#define print_arr(begin,end) for(auto it = begin;it!=end;it++) cout<<*it<<" "; cout<<endl;
#define log_this(name,value) cout<<name<<": "<<value<<endl;
#define e5 100005
#define e6 1000006
using namespace std;
ll to_ll(string s) {stringstream ss;ss<<s<<endl;ll a;ss>>a;return a;}
string to_str(double a) {stringstream ss;ss<<a<<endl;return ss.str();}
template<class T>inline void read(T &x){T f=1;x=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}x*=f;}
map<int,ll>eg[1*e5];
struct cst_cnt{
ll cst,cnt;
cst_cnt(ll cs,ll cn){cst = cs,cnt = cn;}
bool operator < (const cst_cnt o)const{
return (cst-cst/2)*cnt<(o.cst-o.cst/2)*o.cnt;
}
};
priority_queue<cst_cnt>cost;
ll sum;
ll dfs(int i,int last){
ll cst;
if(i==last) cst = 0;
else cst = eg[i][last];
ll cnt = 0;
if(eg[i].size()==1&&i!=last) cnt = 1;
else{
for(auto it:eg[i]){
if(it.first!=last){
cnt += dfs(it.first,i);
}
}
}
sum += cnt*cst;
cost.push(cst_cnt(cst,cnt));
return cnt;
}
int main(){
int t;cin>>t;
while(t--){
ll n,s;cin>>n>>s;
frr(i,1,n+1) eg[i].clear();
ll v,u,w;
#define p(a,b) pair<int,ll>(a,b)
fr(i,n-1){
cin>>v>>u>>w;
eg[v].insert(p(u,w));
eg[u].insert(p(v,w));
}
while(!cost.empty()) cost.pop();
sum = 0;
dfs(1,1);
ll ans = 0;
while(sum>s){
cst_cnt tmp = cost.top();
sum -= (tmp.cst-tmp.cst/2)*tmp.cnt;
tmp.cst/=2;
cost.pop();
cost.push(tmp);
ans++;
}
cout<<ans<<endl;
}
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/6734.html
標籤:其他
