牛客练习赛7

骰⼦的游戏
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

    在Alice和Bob面前的是两个骰子,上面分别写了六个数字。

    Alice和Bob轮流丢掷骰子,Alice选择第一个骰子,而Bob选择第二个,如果谁投掷出的数更大,谁就可以获胜。

    现在给定这两个骰子上的6个数字,你需要回答是Alice获胜几率更大,还是Bob获胜几率更大。(请注意获胜几率相同的情况)

 

输入描述:

第一行一个数T,表示数据个数。
接下来的每一组数据一共有2行,每一行有6个正整数,第一行是第一个骰子上的6个数,第二行是第二个骰子上的6个数。

输出描述:

如果Alice获胜几率更大,你需要输出Alice;
如果Bob获胜几率更大,你需要输出Bob;
如果获胜几率一样大,你需要输出Tie。
示例1

输入

2
3 3 3 3 3 3
1 1 4 4 4 4
1 2 3 4 5 6
6 5 4 3 2 1

输出

Bob
Tie

说明

第一个数据中,Alice有三分之一几率获胜,Bob有三分之二几率获胜;
第二个数据中,Alice和Bob的骰子完全一致,所以获胜几率一样大。

备注:

对于30%的数据,1 ≤ T ≤ 10。

对于60%的数据,1 ≤ T ≤ 1000。

对于100%的数据,1 ≤ T ≤ 10^5,所有输入的数均 ≤ 10^7。

直接比较大小就可以了

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,a[10],b[10];
    scanf("%d",&n);
    while(n--)
    {
        for(int i=0; i<6; i++)
            scanf("%d",&a[i]);
        for(int i=0; i<6; i++)
            scanf("%d",&b[i]);
        int s=0,t=0;
        for(int i=0; i<6; i++)
            for(int j=0; j<6; j++)
            {
                if(a[i]>b[j])s++;
                if(a[i]<b[j])t++;
            }
        if(s==t)puts("Tie");
        else if(s>t)puts("Alice");
        else puts("Bob");
 
    }
    return 0;
}

 以下代码适合a,b数组特别大的时候

nlogn解决这个a数组大于b数组的个数,无法更快解决吧,感觉两个指针可以把有序数组这个优化下

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,a[10],b[10];
    scanf("%d",&n);
    while(n--)
    {
        for(int i=0; i<6; i++)
            scanf("%d",&a[i]);
        for(int i=0; i<6; i++)
            scanf("%d",&b[i]);
        sort(a,a+6);
        sort(b,b+6);
        int s=0,t=0;
        for(int i=0;i<6;i++)
            s+=lower_bound(a,a+6,b[i])-a;
        for(int i=0;i<6;i++)
            t+=lower_bound(b,b+6,a[i])-b;
        if(s==t)puts("Tie");
        else if(s<t)puts("Alice");
        else puts("Bob");
    }
    return 0;
}

我想的尺取贪心写不大出来,感觉二分够了,顶多加个离散化

购物
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

在遥远的东方,有一家糖果专卖店。
这家糖果店将会在每天出售一些糖果,它每天都会生产出m个糖果,第i天的第j个糖果价格为C[i][j]元。
现在的你想要在接下来的n天去糖果店进行选购,你每天可以买多个糖果,也可以选择不买糖果,但是最多买m个。(因为最多只生产m个)买来糖果以后,你可以选择吃掉糖果或者留着之后再吃。糖果不会过期,你需要保证这n天中每天你都能吃到至少一个糖果。
这家店的老板看你经常去光顾这家店,感到非常生气。(因为他不能好好睡觉了)于是他会额外的要求你支付点钱。具体来说,你在某一天购买了 k 个糖果,那么你在这一天需要额外支付 k2 的费用。

那么问题来了,你最少需要多少钱才能达成自己的目的呢?

 

输入描述:

第一行两个正整数n和m,分别表示天数以及糖果店每天生产的糖果数量。
接下来n行(第2行到第n+1行),每行m个正整数,第x+1行的第y个正整数表示第x天的第y个糖果的费用。

输出描述:

输出只有一个正整数,表示你需要支付的最小费用。
示例1

输入

3 2 
1 1
100 100 
10000 10000

输出

107
示例2

输入

5 5
1 2 3 4 5
2 3 4 5 1 
3 4 5 1 2 
4 5 1 2 3 
5 1 2 3 4

输出

10

备注:

对于100%的数据,1 ≤ n, m ≤ 300 , 所有输入的数均 ≤ 106。

dp,前i天买x个最小花费

#include<bits/stdc++.h>
using namespace std;
vector<int>V[305];
int dp[305][305],a[305][305];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            int x;
            scanf("%d",&x);
            V[i].push_back(x);
        }
        sort(V[i].begin(),V[i].end());
        for(int j=1; j<=m; j++)
            a[i][j]=a[i][j-1]+V[i][j-1];
    }
    memset(dp,-1,sizeof dp);
    dp[0][0]=0;
    for(int i=1; i<=n; i++)
        for(int j=i; j<=n; j++)
        {
            for(int k=0; k<=j&&k<=m; k++)
            {
                if(dp[i-1][j-k]!=-1)
                {
                    if(dp[i][j]!=-1)dp[i][j]=min(dp[i-1][j-k]+a[i][k]+k*k,dp[i][j]);
                    else dp[i][j]=dp[i-1][j-k]+a[i][k]+k*k;
                }
            }
        }
    printf("%d",dp[n][n]);
    return 0;
}
珂朵莉的数列
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

珂朵莉给了你一个序列,有个子区间,求出她们各自的逆序对个数,然后加起来输出

输入描述:

第一行一个数 n 表示这个序列 a 的长度

之后一行 n 个数,第i个数表示ai

输出描述:

输出一行一个数表示答案
示例1

输入

10
1 10 8 5 6 2 3 9 4 7

输出

270
示例2

输入

20
6 0 4 5 8 8 0 6 6 1 0 4 6 6 0 0 7 2 0 5

输出

3481

备注:

对于100%的数据,n <=
1000000 ,0 <= 序列中每个数 <= 1000000000

树状数组+二维pair算贡献去求

但是爆了ll

#include<bits/stdc++.h>
using namespace std;;
typedef long long ll;
const int N=1e6+5;
int n,cnt=1,a[N];
pair<int,int> t[N];
ll c[N];
string add(string s1,string s2){
    string s;
    int len1,len2;
    len1=s1.size()-1; len2=s2.size()-1;
    int i=0,f=0;
    while(len1>-1&&len2>-1){
        int sum=f+(s1[len1--]-'0')+(s2[len2--]-'0');
        s+=sum%10+'0';
        f=sum/10;
    }
    while(len1>-1){
        int sum=f+(s1[len1--]-'0');
        s+=sum%10+'0';
        f=sum/10;
    }
    while(len2>-1){
        int sum=f+(s2[len2--]-'0');
        s+=sum%10+'0';
        f=sum/10;
    }
    if(f) s+='0'+f;
    reverse(s.begin(),s.end());
    return s;
}
void add(int k,int x)
{
    while(k>=1)
    {
        c[k]+=x;
        k-=(k&-k);
    }
}
ll query(int k)
{
    ll ans=0;
    while(k<=cnt)
    {
        ans+=c[k];
        k+=(k&-k);
    }
    return ans;
}
void solve()
{
    string ans="0";
    for(int i=1; i<=n; i++)
    {
        ll x=query(a[i]+1)*1LL*(n-i+1);
        string c1="";
        if(x==0)c1+="0";
        while(x)
        {
           c1+=x%10+'0';
           x=x/10;
        }
        reverse(c1.begin(),c1.end());
        ans=add(ans,c1);
        add(a[i],i);
    }
    cout<<ans<<endl;
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        t[i]=make_pair(a[i],i);
    }
    sort(t+1,t+n+1);
    for(int i=1; i<=n; i++)
    {
        if(t[i-1].first!=t[i].first)
        {
            cnt++;
        }
        a[t[i].second]=cnt;
    }
    solve();
    return 0;
}

__int128写法

#include<bits/stdc++.h>
using namespace std;;
typedef long long ll;
const int N=1e6+5;
int n,cnt=1,a[N];
pair<int,int> t[N];
ll c[N];
void print(__int128 x)
{
    if (x==0) return;
    if (x) print(x/10);
    putchar(x%10+'0');
}
void add(int k,int x)
{
    while(k>=1)
    {
        c[k]+=x;
        k-=(k&-k);
    }
}
ll query(int k)
{
    ll ans=0;
    while(k<=cnt)
    {
        ans+=c[k];
        k+=(k&-k);
    }
    return ans;
}
void solve()
{
    __int128 ans=0;
    for(int i=1; i<=n; i++)
    {
        ans+=query(a[i]+1)*1LL*(n-i+1);
        add(a[i],i);
    }
    if(ans==0)putchar('0');
    print(ans);
}
int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        t[i]=make_pair(a[i],i);
    }
    sort(t+1,t+n+1);
    for(int i=1; i<=n; i++)
    {
        if(t[i-1].first!=t[i].first)cnt++;
        a[t[i].second]=cnt;
    }
    solve();
    return 0;
}

 

posted @ 2017-12-02 18:57  暴力都不会的蒟蒻  阅读(448)  评论(0编辑  收藏  举报