A. Ace Arbiter
题意:乒乓球11分制比赛,换发制,发球顺序是ABBAABBAABB这种,裁判按照时间顺序随机爆出比分,左边是发球方的比分,然后问哪个给出的比分是错误的
思路:先根据x+y分数判断是哪一仑,然后判断是左边是A还是B,然后判断当前分数与上一个分数是否符合规则,遇到11则结束了,后方如果还得分就错了
diamond:
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200010];
int32_t main(){
int x,y;
int n;
cin>>n;
int la=0,lb=0;
int k=-1;
int st=0;
for (int i = 1; i <=n ; ++i) {
char g;
cin >> x >> g >> y;
if(st)continue;
int lun = x + y + 1;
int dq;
if ((lun / 2) % 2 == 0) {
dq = 0;
} else {
dq = 1;
}
int sa, sb;
if (dq == 1) {
sb = x;
sa = y;
} else {
sa = x;
sb = y;
}
if (sa < la || sb < lb) {
k =i;
st=1;
}
if(la==11&&sb>lb||lb==11&&sa>la){
k =i;
st=1;
}
if(sa==11&&sb==11){
k =i;
st=1;
}
la=sa;
lb=sb;
}
if(st){
cout<<"error "<<k;
}
else{
cout<<"ok";
}
}
G. Graduation Guarantee
题意:给n个题目,我们可以任选i个题目做,给出题目的正确率,赛前可以看到正确率,做对得1分,做错-1分,问要得到>=k分,最大概率是多少
思路:我们可知概率的大小,排序,从大的开始取,$f[i][j]$代表取i个题目,得j分的概率是多少,那么$f[i][j]=f[i-1][j] * (1-p[i])+f[i-1][j-1] * p[i]$,如果j-(i-j)>=k,则加入sum,每遍历完一个i,取一次max
diamond:
//
// Created by hrk on 8/8/AD2023.
//
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define LL long long
double f[5010][5010],p[5010];
int32_t main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>p[i];
}
sort(p+1,p+1+n,greater<double>());
f[0][0]=1;
double ans=0;
for(int i=1;i<=n;i++){
double sum=0;
for(int j=0;j<=i;j++){
f[i][j]=f[i-1][j]*(1-p[i])+f[i-1][j-1]*p[i];
int shu=i-j;
if(j-shu>=k){
// cout<<ans<<'\n';
sum+=f[i][j];
}
}
ans=max(ans,sum);
}
cout<<ans<<'\n';
return 0;
}
B. Berry Battle
题意:在一颗树上的每个节点都有一个果子和一只蚂蚁,你的目的是摘掉树上所有的果子,你每摘一个果子树上不在该点的蚂蚁就会往该点移动一步,在该点的蚂蚁则不动,当所有的蚂蚁都在一个点的时候你就会被蚂蚁杀死,现给定n-1条边,让你判断是否存在这样一个顺序使得你可以摘完所有的果子且不被蚂蚁杀死。若存在,输出YES并输出该排列,否则输出NO。
思路:
找到树的重心,这里重心的意思是树上每个点到该点的距离最大值最小的点,可以先跑dfs求出树的直径,到两端距离最小的点即为重心。 若n<=3,则无论怎样都不可能存在这么一个排列; 若n>3,因为重心至少有两个子树存在,以重心为根节点的树当中,只要有一个子树的深度>1,则一定存在这么一个排列。
在此举例:最坏的情况就是n=4,且树为一条链的时候,易得2或3为树的重心 2-1,2-3,1-4 此时,先选树的重心2,在选深度不为2的任意一条边的点,之后层次遍历输出即可。
diamond:
#include<bits/stdc++.h>
#include<vector>
#include<set>
#include<map>
#include<cstring>
#include<stack>
#include<queue>
#include<unordered_map>
#include<unordered_set>
using namespace std;
#define ll long long
#define ull unsigned long long
#define endl '\n'
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define pii pair<int,int>
#define pdd pair<double,double>
#define mp make_pair
#define pll pair<ll,ll>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=300010,M=600010;
vector<int> v[N];
int dist[N],d[N],s[N];
bool st[N];
void dfs(int u,int fa){
dist[u]=dist[fa]+1;
for(auto e:v[u]){
if(e==fa) continue;
dfs(e,u);
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<n;i++){
int a,b;cin>>a>>b;
v[a].push_back(b);
v[b].push_back(a);
}
dfs(1,1);
int pos=1,maxx=0;
for(int i=1;i<=n;i++){
if(dist[i]>maxx) maxx=dist[i],pos=i;
}
dist[pos]=0;
dfs(pos,pos);
maxx=0;
for(int i=1;i<=n;i++){
d[i]=dist[i];
if(dist[i]>maxx) maxx=dist[i],pos=i;
}
dist[pos]=0;
dfs(pos,pos);
int zhong,Min=INF; //zhong即为树的重心
for(int i=1;i<=n;i++){
d[i]=max(d[i],dist[i])-1;
if(d[i]<Min){
Min=d[i];
zhong = i;
}
}
if(n<=3) cout<<"NO";
else{
int flag=0;
for(auto e:v[zhong]){
if(v[e].size() >1){ //因为是无向边,所以只要size>1则意味着深度>1
flag=e;
}
}
if(flag) for(auto e:v[zhong]){ //若存在深度>1的子树,则随便找一个不在这子树的点标记为flag
if(e!=flag){
flag=e;break;
}
}
if(!flag) cout<<"NO"; //若没找到则直接输出NO
else{
cout<<"YES"<<endl;
cout<<zhong<<' '; //先走重心
st[zhong]=true;
queue<int> qu;
qu.push(flag);
st[flag]=true;
//往后正常层次遍历即可
for(auto e:v[zhong]){
if(!st[e]){
qu.push(e);
st[e]=true;
}
}
while(qu.size() ){
auto e=qu.front() ;
qu.pop() ;
cout<<e<<' ';
for(auto u:v[e]){
if(!st[u]){
qu.push(u);
st[u]=true;
}
}
}
}
}
return 0;
}