AtCoder Beginner Contest 190 题解

很舒服

Posted by Lin_Xuan on January 30, 2021

传送门: AtCoder Beginner Contest 190

5道题……没有AK过的菜鸡想AK啊!!

A:Very Very Primitive Game

很简单的逻辑判断

    int a,b,c;
    cin>>a>>b>>c;
    if(a>b) cout<<"Takahashi"<<endl;
    else if(a<b) cout<<"Aoki"<<endl;
    else cout<<(c==0?"Aoki":"Takahashi")<<endl;

B:Magic 3

签到~

    int n,s,d;
    cin>>n>>s>>d;
    bool flag=false;
    for(int i=1;i<=n;i++)
    {
        int a,b;
        cin>>a>>b;
        if(a<s and b>d) flag=true;
    }
    if(flag) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;

C:Bowls and Dishes

二选一,数据范围16,直接暴力,dfs枚举$2^{16}$中情况即可。

#include<bits/stdc++.h>

#define IOS ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);

#define x first

#define y second 

using namespace std;
using LL=long long;
using ULL=unsigned long long;
using LD=long double;
using P=pair<int,int>;
const int inf=0x3f3f3f3f;
const LL LLinf=0x3f3f3f3f3f3f3f3f;

int n,m,k;
vector<P> condition,opration;
vector<int> vis;
int dfs(int i)
{
    if(i>k)
    {
        int cnt=0;
        for(int i=1;i<=m;i++)
            if(vis[condition[i].x]>0 and vis[condition[i].y]>0) cnt++;
        return cnt;
    }
    vis[opration[i].x]++;
    int ans1=dfs(i+1);
    vis[opration[i].x]--;
    vis[opration[i].y]++;
    int ans2=dfs(i+1);
    vis[opration[i].y]--;
    return max(ans1,ans2);
}
int main()
{
    cin>>n>>m;
    condition.assign(m+1,P(0,0));
    vis.assign(n+1,0);
    for(int i=1;i<=m;i++)
        cin>>condition[i].x>>condition[i].y;
    cin>>k;
    opration.assign(k+1,P(0,0));
    for(int i=1;i<=k;i++)
        cin>>opration[i].x>>opration[i].y;
    int ans=dfs(1);
    cout<<ans<<endl;
    return 0;
}

D:Staircase Sequences

解题方法:

差为1的等差数列的和为n,则设等差数列的项数为k项,中间值为m。(中间值为奇数项的等差中项,偶数项两个等差中项的平均值),则$k\times m=n$ 。如果m为分数,则只能为$\frac{1}{2}$的倍数(差为1的两个整数的平均数)。令M=2m必为整数。$k\times M=2n$,$k=\frac{2n}{M}$必须为整数,M,k是2n的因数。同时注意,M为偶数的时候说明m是整数,则k必须为奇数(奇数项m为整数)。如果M为奇数,则说明m为分数,一定是偶数项。

枚举2n的因数,判断即可。

代码:

#include<bits/stdc++.h>

using namespace std;
using LL=long long;
using ULL=unsigned long long;
using LD=long double;
using P=pair<int,int>;
const int inf=0x3f3f3f3f;
const LL LLinf=0x3f3f3f3f3f3f3f3f;
// AC
int main()
{
    LL n;
    cin>>n;
    LL m=n<<1;
    LL cnt=0;
    for(int i=1;i<=sqrt(m);i++)
    {
        if(m%i==0)
        {
            LL tmp=i;
            if((tmp&1)==1 and ((m/tmp)&1)==0) cnt++;
            else if((tmp&1)==0 and ((m/tmp)&1)==1) cnt++;
            tmp=m/i;
            if(tmp!=i)
                if((tmp&1)==1 and ((m/tmp)&1)==0) cnt++;
                else if((tmp&1)==0 and ((m/tmp)&1)==1) cnt++;
        }
    }
    cout<<cnt<<endl;
    return 0;
}

E:Magical Ornament

待补题

F:Shift and Inversions

解题方案:

简单理解一下,题目为每次将数列的第一个数放到队尾,分别求逆序对的个数。采用树状数组求逆序对的方法即可。

树状数组可以快速求得比队首的数小的数的数量,极为拿掉队首逆序对将减少的数量。同时将这个数放到队尾,使用树状数组求该数前面大于它的数的数量,极为逆序对增加的数量。重复k-2次该过程即可。

代码:

#include<bits/stdc++.h>

using namespace std;
using LL=long long;
using ULL=unsigned long long;
using LD=long double;
using P=pair<int,int>;
const int inf=0x3f3f3f3f;
const LL LLinf=0x3f3f3f3f3f3f3f3f;
//  AC

const int N=5e5+5;
//区间查询,单点修改
int a[N]={0};
LL c[N]={0};
int lowbit(int x){
    return x&(-x);
}
void update(int i,int n,int v)
{
    while(i<=N)
    {
        c[i]+=v;
        i+=lowbit(i);
    }
}

LL get_sum(int i)
{
    LL x=0;
    while(i>0)
    {
        x+=c[i];
        i-=lowbit(i);
    }
    return x;
}

int main()
{
    int n;
    cin>>n;
    queue<int> que;
    LL ans=0;
    for(int i=1;i<=n;i++){
        int x; cin>>x;
        x++;//要从1计
        ans+=get_sum(n)-get_sum(x);//比x大的数量
        update(x,n,1);
        que.push(x);
    }
    cout<<ans<<endl;
    for(int k=1;k<=n-1;k++)
    {
        int val=que.front();
        que.pop();
        ans-=get_sum(val-1);//有多少比val小
        ans+=get_sum(n)-get_sum(val);//有多少比val大
        cout<<ans<<endl;
    }
    return 0;
}