[题解]牛客练习赛69ABC

题号 标题
A 时间复杂度
B 划分
C [旅行]

A

题目描述

DK 想出一道超级没有素质的题

DK 给了你一个标准的时钟,初始时间在 12:00

每分钟分针会顺时针转动 6°,而时针会顺时针转动 0.5°

DK 想知道,t 分钟后,时针和分针的较小夹角的大小是多少

由于这题超级没有素质,所以你需要将答案四舍五入到整数

输入描述:

第一行一个整数 n,表示数据组数

第 2 ~ n+1行,每行一个整数 t,意义见题目描述

输出描述:

输出n行,每行一个整数,表示答案


题解

此题是模拟题,难点在于那个0.5,可以事先用 if else 判断再对结果进行调整,也可以直接用double来模拟,最后再四舍五入。

#define Oo ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#include <bits/stdc++.h>
using namespace std;
#define PI acos(-1.0)
typedef long long ll;
int solve(int time)
{
      double f=(int)(6*time)%360;
      double h=time/2.0;
      double t1=abs(f-h);
      double t2=abs(360-t1);
      int ans=ceil(min(t1, t2));
      return ans;
}
int main()
{
      Oo
      int __;
      cin>>__;
      while(__--)
      {
            int t;cin>>t;
            if (t==720)cout<<0 << endl;
            else
            cout << solve(t) << endl;
      }
	return 0;
}

B

题目描述

给你一个长度为 n 的序列,第 i 个数为 a_i

将这个序列分割成 i 个不重合的子串,从每个子串中取出最大的 j 个数作为这个分割方法的价值,记价值最大的分割方法的价值为 val(i,j)

但是金发少女 DK 觉得这太好算了,于是她要你求下面的柿子

∑ i = 1 x ∑ j = 1 y v a l ( i , j ) \sum_{i=1}^{x}\sum_{j=1}^{y}val(i,j) i=1xj=1yval(i,j)

输入描述:

第一行输入一个正整数 n第二行输入 n 个正整数,第 i 个数表示 ai第三行输入两个正整数 x,y,含义如题中所示

输出描述:

一个数,表示答案

数据范围:

1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 , x × y < = n 1≤n≤10^5, 1\le a_i\le 10^9, x\times y<=n 1n105,1ai109,x×y<=n


题解

对于一个确定的 X,Y ,答案一定是可以取到前 X × Y X\times Y X×Y 个最大的值,所以只需要排序,再维护一个前缀和。

#define Oo ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#include <bits/stdc++.h>
using` `namespace` `std;
#define PI acos(-1.0)
typedef` `long` `long` `ll;
ll a[100005];
ll temp[100005];
int` `main()
{
   ``Oo
   ``ll n; cin>>n;
   ``for` `(``int` `i=0; i<n; i++)cin>>a[i];
   ``sort(a, a+n, greater<ll>());
   ``ll x, y;cin>>x >> y;
   ``for` `(``int` `i=0; i<n; i++)
   ``{
      ``if` `(i==0)temp[i]=a[i];
      ``else` `temp[i]=temp[i-1]+a[i];
   ``}
   ``ll ans=0;
   ``for` `(``int` `i=1; i<=x; i++)
   ``{
      ``for` `(``int` `j=1; j<=y; j++)
      ``{
         ``ans+=temp[i*j-1];
      ``}
   ``}cout << ans << endl;
  ``return` `0;
}

C

题目描述

DK 有一个无向图 G,这个无向图有 n 个点 m 条边
你需要确定一个大小为 n 的排列 a,使 ∑ i = 2 n dis ⁡ ( a i − 1 , a i ) \sum\limits_{i=2}^n \operatorname{dis}(a_{i-1},a_i) i=2ndis(ai1,ai) 最大,求这个最大值
dis ⁡ ( u , v ) \operatorname{dis}(u,v) dis(u,v)表示从 u 到 v 的路径的中最短的边的边权,若有多条路径,则选令 dis ⁡ ( u , v ) \operatorname{dis}(u,v) dis(u,v)最大的路径

输入描述:

第一行两个正整数 n,m接下来 m 行,每一行三个正整数 u,v,w 表示 u,v 之间有一条长度为 w 的边

输出描述:

表示最大的
∑ i = 2 n dis ⁡ ( a i − 1 , a i \sum\limits_{i=2}^n \operatorname{dis}(a_{i-1},a_i i=2ndis(ai1,ai


题解

这个思路和最小生成树一模一样,就是求最大生成树而已。

#define Oo ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#include <bits/stdc++.h>
using namespace std;
#define PI acos(-1.0)
typedef long long ll;
struct node
{
      ll x;
      ll y;
      ll w;
}a[500005];
ll cmp(node a , node b ){return a.w>b.w;}
ll f[500005];
ll _find(ll i)
{
      if (i==f[i])return i;
      else return f[i]=_find(f[i]);
}
int main()
{
      Oo
      ll n, m;
      cin>> n >> m;
      for (int i=0; i<m; i++)cin>>a[i].x>>a[i].y>>a[i].w;
      for (int i=1; i<=n; i++)f[i]=i;
      sort(a, a+m, cmp);
      ll ans=0;
      for (int i=0; i<m; i++)
      {
            int tx=_find(a[i].x);
            int ty=_find(a[i].y);
            if (tx!=ty)
            {
                  f[tx]=ty;
                  ans+=a[i].w;
            }
      }
      cout << ans << endl;
	return 0;
}

个人heox博客

猜你喜欢

转载自blog.csdn.net/osusoer/article/details/108566419