czl蒻蒟的OI之路5

  • XJOI奋斗群蒻蒟群群赛6 RANK排名10
      • T1Fraction已AC
          • 题意
          • 分析过程
          • 给出题解
      • T2Maxim Buys an Apartment WA两次AC
          • 题意
          • 分析过程
          • 给出题解
      • T3PlanningTLE两次后AC
          • 题意
          • 分析过程
          • 给出题解
      • T4Jury Meeting已AC
          • 题意
          • 分析过程
          • 给出题解
      • 蒻蒟的总结

—>XJOI奋斗群(蒻蒟群)群赛6<— RANK排名10

T1:Fraction(已AC)

题意:

定义一个分数,如果这个分数的分子小于分母,则该分数为适当分数。如果一个分数的分子和分母互质,那么这个分数成为不可约分数。给你一个分子与分母的和,让你计算最大的适当不可约分数的分子和分母。

分析过程:

既然是适当分数,那么分子一定严格小于分母,所以可以从和的一半开始向下枚举,如果枚举到一个数,使得分子和分母互质,这个数就会使分数最大,并满足条件。

给出题解:
#include
using namespace std;

int get_gcd(int a,int b)
{
    int c;
    c=min(a,b);
    for(int i=c;i>=1;i--)
    {
        if(a%i==0&&b%i==0)return i;
    }
}
int main()
{
    int n;
    int zi,mu;
    int a,b;
    int gcd;
    cin>>n;
    for(int zi=n/2;zi>=1;zi--)
    {
        mu=n-zi;
        gcd=get_gcd(zi,mu);
        if(gcd==1)
        {
            a=zi;
            b=mu;
            break;
        }
    }
    cout<" "<

T2:Maxim Buys an Apartment (WA两次AC)

题意:

给你总共的公寓的数量n和已经入住的人数k,要求再入住一个人,使得这个人的旁边必须有人住。然后让你计算这个人可以居住的公寓数量的最大值与最小数。

分析过程:

首先是两个特例,如果n等于k或者k等于零,可以直接输出两个0,其他的再继续判断。当k很小的时候,每个人可以提供2个可住的公寓的个数。而当k比较大的时候最大的可入住人数为n-k。而在k比较小的时候,n-k的个数一定比k*2大。所以只要选择n-k和k*2的比较小的值输出就行了。

给出题解:
#include
using namespace std;

int main()
{
    int n,k;
    int mint,max;
    cin>>n>>k;
    if(k==0||k==n)
    {
        max=mint=0;
    }
    else 
    {
        mint=1;
        max=min(n-k,k*2);
    }
    cout<" "<

T3:Planning(TLE两次后AC)

题意:

给你一个航班的安排,结果航班延迟了,要求在时间k之前飞机不能出发,并且飞机出发时间不能早于它原来的时间。每个飞机都有成本,如果飞机延迟出发n分钟,费用就为n*成本。要你求最小的成本。

分析过程:

思路其实很简单,只需要一个贪心就行了。既然要让成本最小,就是要让每个航班的成本最小。所以从最大的成本开始向下遍历,求出满足每个航班的成本最小的t的最大值,计算总花费,最后输出每个航班的出发时间。
但是!!!!!这样并不能AC,保证TLE。就算把复杂度降到了O(nlog n)都还是一样。最后在别人和百度的指导下学会了用优先队列,时间复杂度降到了O(log n),就AC了。关于优先队列,接下来会出一篇专门讲的。

给出题解:
#include
#define maxn 300050
#define LL  long long 
using namespace std;

    LL n,k;
    LL  x,t,ans=0;
struct flight
{
    int x;
    int money;
    friend bool operator<(flight a,flight b)
    {
        return a.moneyint main()
{
    int f[maxn];
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>fly[i].money;
        fly[i].x=i;
    }
    priority_queueq;
    for(int i=1;i<=k;i++)
    {
        q.push(fly[i]);
    }
    for(int i=k+1;i<=k+n;i++)
    {
        if(i<=n)q.push(fly[i]);
        flight t=q.top();
        q.pop();
        ans=ans+(LL)(i-t.x)*(LL)(t.money);
//      cout<
        f[t.x]=i;
    }
    cout<for(int i=1;i<=n;i++){
        cout<" ";
    }
    return 0;
}

T4:Jury Meeting(已AC)

题意:

有n个城市,要在第0个城市召开会议,持续k天。有m个航班,都是第0个城市与其他城市之间的,每个航班有不同的起飞时间与花费。问你能不能让所有人都到达第0个城市,开完k天的会议后都回到原来的城市,若果有,输出最小花费,如果没有,输出NO。

分析过程:

这题可以用贪心来解,首先,可以吧飞机分为两种,去0的和从0去别的地方的。先把这两种飞机进行时间上的排序,然后先从前面开始遍历,找出一个每一个点所需花费的钱,并找到一个点,所有的会议人员都可以到达0。然后从后面开始遍历,找出每一个点所需花费的钱,并且找出一个点,所有的会议人员必须启程的日子(即再往后就会有会议人员无法回到远程市)。最后在这两个区间中遍历点,找出去0的机票花费+回去的机票花费的最小值,即为题目所求。

给出题解:
#include
using namespace std;
typedef long long ll;
#define inf (ll)1e17
#define maxn  2100005
struct node
{
    ll day,from,to,cost;
} a[maxn];
bool comp(node a, node b)
{
    return a.day < b.day;
}
ll b[maxn], dp[maxn], dp1[maxn];
int main()
{
//  freopen("in.txt","r",stdin);
    ll n, k, m, i, j;
    cin>>n>>m>>k;
    for (i = 0; i <= 2100000; i++)
        b[i] = -1, dp[i] = inf;
    for (i = 1; i <= m; i++)
        cin>>a[i].day>>a[i].from>>a[i].to>>a[i].cost;
    sort(a + 1, a + m + 1, comp);
    ll num = 0, sum = 0;
    for (i = 1; i <= m; i++)
    {
        if (a[i].from == 0)
            continue;
        if (b[a[i].from] == -1)
            num++, b[a[i].from] = a[i].cost, sum += a[i].cost;
        else
        {
            if (b[a[i].from] > a[i].cost)
            {
                sum -= b[a[i].from];
                b[a[i].from] = a[i].cost;
                sum += a[i].cost;
            }
        }
        if (num == n)
            dp[a[i].day] = sum;
    }
    num = 0;
    sum = 0;
    for (i = 0; i <= 2100000; i++)
        b[i] = -1, dp1[i] = inf;
    for (i = m; i > 0; i--)
    {
        if (a[i].to == 0)
            continue;
        if (b[a[i].to] == -1)
            num++, b[a[i].to] = a[i].cost, sum += a[i].cost;
        else
        {
            if (b[a[i].to] > a[i].cost)
            {
                sum -= b[a[i].to];
                b[a[i].to] = a[i].cost;
                sum += a[i].cost;
            }
            if (num == n)
                dp1[a[i].day] = sum;
        }
        if (num == n)
            dp1[a[i].day] = sum;
    }
    for (i = 1; i <= 1000000; i++)
        if (dp[i] != inf)
            break;
    j = i;
    for (i = j + 1; i <= 1000000; i++)
        dp[i] = min(dp[i - 1], dp[i]);
    for (i = 1000000; i > 0; i--)
        if (dp1[i] != inf)
            break;
    j = i;
    for (i = j - 1; i > 0; i--)
        dp1[i] = min(dp1[i], dp1[i + 1]);
    ll ans = inf;
    for (i = 1; i <= 1000000; i++)
    {
        if (dp[i] == inf || dp1[i + k + 1]==inf)  continue;
        ans = min(dp[i] + dp1[i + k + 1], ans);
    }
    if (ans == inf)cout<<-1;
    else cout<;
    return 0;

蒻蒟的总结:

今天只有4个题目,前面两个算是比较水的题目,然而第二题还是WA了两次,这点要抓紧改正。后两题,用到堆和动态规划(可能…),而这些我都不怎么熟,所以自己不懂的东西还有很多。明天不出意外,是要跑两圈的,加油吧少年。

继续贴出吴老师的话:学信息的人永不服输!!!

你可能感兴趣的:(蒟蒻OI之路)