A
题意:给你4个从小到大的数a,b,c,d
找出任一一组分别在[a,b],[b,c],[c,d]中的三个数,使得他们可以构成三角形的三边长。题目保证答案存在。
解:b,c,c 必定符合题意。输出即可
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
#define ll long long
using namespace std;
int a[5],T;
int ans[5];
signed main(){
//freopen("test.in","r",stdin);
cin>>T;
while(T--){
cin>>a[1]>>a[2]>>a[3]>>a[4];
printf("%d %d %d\n",a[2],a[3],a[3]);
}
return 0;
}
B
题意:有一只大龙血量为hp,你可以使用n次技能A和m次技能B。问你是否能够打败它(使他血量低于0)
技能A hp=》[hp/2]+10;
技能B hp-=10;
解:
经计算,对于任意hp>20,技能A会使hp减少,而当hp<20,技能A会使hp增加。技能B一定会使hp减少。最优伤害计算方法为当hp>20,使用技能A,当hp<=20 使用技能B。由于数据范围比较小,可以直接计算。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
#define ll long long
using namespace std;
int hp,n,m,T;
signed main(){
//freopen("test.in","r",stdin);
cin>>T;
while(T--){
cin>>hp>>n>>m;
while(n--&&hp>20){
hp=hp/2+10;
}
while(m--){
hp-=10;
}
if(hp<=0)cout<<"YES";
else cout<<"NO";
cout<<"\n";
}
return 0;
}
C
题目大意;给一棵树,选择k个点使得这k个结点往祖先结点回溯时非k点的数目和最大。
因为每个子树的深度越大越优,所以每颗子树上结点的选取相对顺序可以确定,并且可以计算每个结点对答案的贡献深度减去儿子的数量即dp[n]-sons[n].计算,排序即可。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
#define ll long long
using namespace std;
const ll maxn=2e5+10;
ll n,k;
ll tol=0,first[maxn];
struct edge{
ll to,next;
}e[maxn*2];
void addedge(ll from,ll too){
tol++;
e[tol].to=too;
e[tol].next=first[from];
first[from]=tol;
}
ll vis[maxn],d[maxn],sons[maxn];
ll a[maxn];
void spfa(){
memset(d,0x3f,sizeof(d));
d[1]=0;
queue<ll>q;
q.push(1);
vis[1]=1;
while(!q.empty()){
ll now=q.front();q.pop();
for(ll i=first[now];i;i=e[i].next){
ll v=e[i].to;
if(vis[v])continue;
vis[v]=1;
d[v]=d[now]+1;
q.push(v);
}
}
}
void dfs(ll x){
for(ll i=first[x];i;i=e[i].next){
ll v=e[i].to;
if(d[v]==d[x]+1){
dfs(v);
sons[x]+=(sons[v]+1);
}
}
}
signed main(){
//freopen("test.in","r",stdin);
cin>>n>>k;
for(ll x,y,i=2;i<=n;i++){
cin>>x>>y;
addedge(x,y);
addedge(y,x);
}
spfa();
dfs(1);
for(ll i=1;i<=n;i++){
a[i]=d[i]-sons[i];
}
sort(a+1,a+n+1);
ll temp=n,ans=0;
while(k--){
ans+=a[temp--];
}
cout<<ans<<'\n';
return 0;
}
D:
题意:给三个序列r,g,b;
每个序列选择一个数 x,y,z;
找出最小的(x−y)2+(y−z)2+(z−x)2最小;
解:
x 预处理每个x的第一个比它大的lessy,lessz;第一个比他小的hugey,hugez;
x为第二大(中间数)的最优组合(x,y,z)必在(x,lessy,hugez)和(x,hugey,lessz)遍历求出;
y,z 同理。
#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(long long i=a;i<=b;++i)
#define ll unsigned long long
using namespace std;
const ll maxn=1e5+10;
ll T;
ll nr,ng,nb;
ll r[maxn],g[maxn],b[maxn];
ll tolans=0;
ll ans[15][maxn];
ll sum(ll x,ll y,ll z){
return (x-y)*(x-y)+(y-z)*(y-z)+(x-z)*(x-z);
}
void getnext(ll array[],ll size1,ll brray[],ll size2){
tolans++;
ll tol=1;
for(ll i=1;i<=size1;i++){
while(brray[tol]<array[i]&&tol<size2)tol++;
ans[tolans][i]=brray[tol];
}
}
void getlast(ll array[],ll size1,ll brray[],ll size2){
tolans++;
ll tol=size2;
for(ll i=size1;i>=1;i--){
while(brray[tol]>array[i]&&tol>1)tol--;
ans[tolans][i]=brray[tol];
}
}
signed main(){
//freopen("test.in","r",stdin);
cin>>T;
while(T--){
tolans=0;
ll anss=0x3fffffffffffffff;
cin>>nr>>ng>>nb;
for(ll i=1;i<=nr;i++)cin>>r[i];
for(ll i=1;i<=ng;i++)cin>>g[i];
for(ll i=1;i<=nb;i++)cin>>b[i];
sort(r+1,r+nr+1);sort(g+1,g+ng+1);sort(b+1,b+nb+1);
getnext(r,nr,b,nb);
getlast(r,nr,g,ng);
getnext(r,nr,g,ng);
getlast(r,nr,b,nb);
getnext(b,nb,g,ng);
getlast(b,nb,r,nr);
getnext(b,nb,r,nr);
getlast(b,nb,g,ng);
getnext(g,ng,r,nr);
getlast(g,ng,b,nb);
getnext(g,ng,b,nb);
getlast(g,ng,r,nr);
for(ll i=1;i<=nr;i++){
ll x=sum(r[i],ans[1][i],ans[2][i]);
ll y=sum(r[i],ans[3][i],ans[4][i]);
anss=min(anss,sum(r[i],ans[1][i],ans[2][i]));
anss=min(anss,sum(r[i],ans[3][i],ans[4][i]));
}
for(ll i=1;i<=nb;i++){
anss=min(anss,sum(b[i],ans[5][i],ans[6][i]));
anss=min(anss,sum(b[i],ans[7][i],ans[8][i]));
}
for(ll i=1;i<=ng;i++){
anss=min(anss,sum(g[i],ans[9][i],ans[10][i]));
anss=min(anss,sum(g[i],ans[11][i],ans[12][i]));
}
cout<<anss<<'\n';
}
return 0;
}
本文精选了四道算法竞赛题目并提供了详细的解题思路及代码实现,包括三角形边长构造、龙血量计算、树中节点选择以及三序列元素组合问题,涵盖了从简单到复杂的算法设计与分析。
483

被折叠的 条评论
为什么被折叠?



