Codeforces Round #635 (Div. 2) A~D
https://codeforces.com/contest/1337/
A. Ichihime and Triangle
题意
给定四个数字 (a,b,c,d(1le ale ble cle dle 1e9)),请给出任意一组满足下述条件的 (x,y,z) 。
- (ale xle b le yle c le z le d)
- (x,y,z) 可以构成三角形
解题
当 (y=z=c) 时,(x) 取 ([a,b]) 中任意值都可以组成一个等腰三角形。
for i in range(int(input())):
a,b,c,d = list(map(int,input().split()))
print(b,c,c)
B. Kana and Dragon Quest game
题意
你在打一个血量为 (x) 的boss,你现在有两种技能可以释放。
- 技能一 Void Absorption:
- 当boss血量为 (h) 时,释放此技能可以使boss血量变成 (lfloor frac{h}{2} floor + 10)
- 技能二 Lightning Strike
- 打击boss造成10点伤害,即 (h-10)
给出一个血量 (x) ,以及可以释放技能一的次数 (n) 和技能二的次数 (m),询问能否杀死boss。
解题
以贪心的方法考虑,当boss血量越高使用技能一打出的效果越好,所以我们的方案是优先尽可能的把技能一打出,再打出剩下的 (m) 个技能二。需要注意的是,当boss血量小于等于20时,技能一就无法造成伤害了,甚至成了回血技。
for i in range(int(input())):
x,n,m = list(map(int,input().split()))
while n>0 and x>20:
x = x//2+10
n-=1
while m>0 and x>0:
x-=10
m-=1
print("YES" if x<=0 else "NO")
C. Linova and Kingdom
题意
有 (n) 个城市,编号从 (1) 到 (n) ,其中 (1) 为首都。在这些城市中有 (n-1) 条双向道路,可以连通两个城市,保证每两个城市之间都存在的唯一的路径可以相互到达,即这是一个全连通的图。
给定一个 (k) ,你需要从 (n) 个城市中选出 (k) 个城市发展工业,其余的城市发展旅游业。每年每个工业城市都会派出一个代表,前往首都,在去的路上代表每经过一个旅游城市就会贡献 (1) 点满意度,询问你可以得到的最大的满意度和是多少。
解题
这是一道大毒瘤题,通过人数不及上一题1/2(悲
首先边为 (n-1) 的全连通图,说明这是一颗树,我们设编号 (1) 的节点为根。
对于一个城市来说,设需要经过他到达首都的其他城市到的数量为 (ct),即这个节点下面的子孙节点个数。设他到达首都需要经过的城市个数,即这个节点的深度 (depth),首都的深度为 (0) 。
当把一个城市选做为工业城市,那么这个城市对满意度的贡献度 (v = depth - ct) 。
选取贡献度最大的 (k) 个城市作为工业城市即可。
#include<bits/stdc++.h>
#define ll long long
#define fr(i,n) for(int i=0;i<n;i++)
#define frs(i,n,flag) for(int i=0;i<n&&flag;i++)
#define frr(i,j,n) for(int i=j;i<n;i++)
#define r_frr(i,j,n) for(int i=n-1;i>=j;i--)
#define frrs(i,j,n,flag) for(int i=j;i<n&&flag;i++)
#define r_frrs(i,j,n,flag) for(int i=n-1;i>=j&&flag;i--)
#define arend(i,n) ((i!=n-1)?" ":"
")
#define memset0(dp) memset(dp,0,sizeof(dp))
#define print_arr(begin,end) for(auto it = begin;it!=end;it++) cout<<*it<<arend(it,end);
#define log_this(name,value) cout<<name<<": "<<value<<endl;
#define e4 10004
#define e5 100005
#define e6 1000006
#define e7 10000007
#define e9 1000000000
#define INF 9999999
using namespace std;
int to_int(string s) {stringstream ss;ss<<s;int a;ss>>a;return a;}
string to_str(double a) {stringstream ss;ss<<a;return ss.str();}
struct node{
int i = 0; //编号
int v = 0; //贡献度
int depth = 0; //深度
vector<int>e; //边
}nodes[2*e5];
int dfs(int i,int last){
int ct = 0;
nodes[i].depth = nodes[last].depth+1;
for(auto it:nodes[i].e) if(it!=last) ct+=dfs(it,i);
nodes[i].v = nodes[i].depth - ct;
return ct+1;
}
int main(){
cin.tie(0);
//ios::sync_with_stdio(false);
//cout<<setiosflags(ios::fixed)<<setprecision(0);
//freopen("1.out","w",stdout);
int n,k;
while(cin>>n>>k){
frr(i,1,n+1){
nodes[i].i = i;
nodes[i].v = 0;
nodes[i].e.clear();
}
fr(i,n-1){
int a,b;cin>>a>>b;
nodes[a].e.push_back(b);
nodes[b].e.push_back(a);
}
nodes[0].depth = -1;
dfs(1,0);
ll ans = 0;
nth_element(
nodes+1,nodes+k+1,nodes+n+1,
[](node a,node b){
return a.v>b.v;
}
);
frr(i,1,k+1) ans += nodes[i].v;
cout<<ans<<endl;
}
return 0;
}
D. Xenia and Colorful Gems
题意
有三个长度分别为 (n_r,n_g,n_r) 的正整数数组 (r,g,b),其中 (1le r_i,g_i,b_ile1e9) 。
询问 ((r_i-g_j)^2+(r_i-b_k)^2+(g_j-b_k)^2) 的最小值。
解题
同样是一道毒瘤题,通过人数接近B题的1/4。
三个 (n) 的范围上限 (1e5) ,很明显这是一道复杂度 (O(nlogn)) 的二分题。
如果想得到最小的 ((r_i-g_j)^2+(r_i-b_k)^2+(g_j-b_k)^2) ,只需要让 (r_i,g_j,b_k) 的取值足够接近就可以了。
这里分类讨论6种情况:
- (r_ile g_j le b_k)
- (r_ile b_k le g_j)
- (g_j le r_i le b_k)
- (g_j le b_k le r_i)
- (b_k le r_i le g_j)
- (b_k le g_j le r_i)
对6钟情况分别考虑,在每种情况中遍历第二个数组,再对另外两个数组二分查找。在满足式子的值中,找出最接近遍历数字的值。
值得一提的是 lower_bound 会得到在值大于等于查询值的位置中,最小的一个。upper_bound 会得到值大于查询值的位置中,最小的一个,他的前一个位置一定是值小于等于查询值的位置中最大的,刚好满足我们的需求。
#include<bits/stdc++.h>
#define ll long long
#define fr(i,n) for(int i=0;i<n;i++)
#define frs(i,n,flag) for(int i=0;i<n&&flag;i++)
#define frr(i,j,n) for(int i=j;i<n;i++)
#define r_frr(i,j,n) for(int i=n-1;i>=j;i--)
#define frrs(i,j,n,flag) for(int i=j;i<n&&flag;i++)
#define r_frrs(i,j,n,flag) for(int i=n-1;i>=j&&flag;i--)
#define arend(i,n) ((i!=n-1)?" ":"
")
#define memset0(dp) memset(dp,0,sizeof(dp))
#define print_arr(begin,end) for(auto it = begin;it!=end;it++) cout<<*it<<arend(it,end);
#define log_this(name,value) cout<<name<<": "<<value<<endl;
#define e4 10004
#define e5 100005
#define e6 1000006
#define e7 10000007
#define e9 1000000000
#define INF 9999999
using namespace std;
int to_int(string s) {stringstream ss;ss<<s;int a;ss>>a;return a;}
string to_str(double a) {stringstream ss;ss<<a;return ss.str();}
#define Array vector<ll>
int nr, ng, nb;
ll ans;
ll p2(ll x){return x*x;}
void solve(Array a,Array b,Array c){
for(auto y:b){
auto px = upper_bound(a.begin(),a.end(),y);
auto pz = lower_bound(c.begin(),c.end(),y);
if(px==a.begin()||pz==c.end()) continue;
ll x = *(--px),z = *pz; //x<=y<=z 已经找到满足式子的最与y接近的x,z
ll res = p2(x-y) + p2(y-z) + p2(x-z);
if(ans>res||ans==-1) ans = res;
}
}
int main(){
cin.tie(0);
//ios::sync_with_stdio(false);
//cout<<setiosflags(ios::fixed)<<setprecision(0);
//freopen("1.out","w",stdout);
int t;
while(cin>>t){
while(t--){
cin>>nr>>ng>>nb;
Array r(nr),g(ng),b(nb);
#define sortit(arr) sort(arr.begin(),arr.end())
fr(i,nr) cin>>r[i]; sortit(r);
fr(i,ng) cin>>g[i]; sortit(g);
fr(i,nb) cin>>b[i]; sortit(b);
ans = -1;
solve(r,g,b); solve(r,b,g);
solve(g,b,r); solve(g,r,b);
solve(b,r,g); solve(b,g,r);
cout<<ans<<endl;
}
}
return 0;
}