AtCoder Beginner Contest 155

A Poor

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int main()
{
    int a,b,c;cin>>a>>b>>c;
    if(a==b&&b!=c||a==c&&b!=c||b==c&&a!=b)
        printf("Yes\n");
    else printf("No\n");
}

B Papers, Please

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int main()
{
    scanf("%d",&n);
    bool flag=true;
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        if(x%2==0&&x%3&&x%5)
            flag=false;
    }
    printf(flag?"APPROVED":"DENIED");
}

C Poll

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
map<string,int>vis;
int n;
string s[N];
int main()
{
    scanf("%d",&n);
    int mx=0;
    for(int i=1;i<=n;i++)
    {
        cin>>s[i];vis[s[i]]++;
        mx=max(mx,vis[s[i]]);
    }
    sort(s+1,s+1+n);
    for(int i=1;i<=n;i++)
        if(vis[s[i]]==mx)
    {
        cout<<s[i]<<endl;
        vis[s[i]]=0;
    }
}

D Pairs
二分答案mid,可以用双指针在O(n)时间内,或者二分在O(nlogn)时间内,分正数和负数讨

论找出乘积小于等于mid的对的数量。根据单调性就可以解决这道问题了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
ll k;
vector<ll>v1,v2;
bool judge(ll m)
{
    m++;
    ll ans=0;
    ll s1=v1.size(),s2=v2.size();
    if(m==0)
    {
        for(int i=0;i<s2;i++)
            if(v2[i]==0) ans+=s1;
        ans+=(ll)s1*(s1-1)/2;
        ans+=(ll)s2*(s2-1)/2;
        ans=(ll)n*(n-1)/2-ans;
        return ans>=k;
    }
    if(m>0)
    {
        for(int i=0;i<s1-1;i++)
        {
            ll x=m/v1[i];
            if(m%v1[i]) x++;
            int k=lower_bound(v1.begin()+i+1,v1.end(),x)-v1.begin();
            ans+=s1-k;
        }
        for(int i=0;i<s2-1;i++)
        {
            if(v2[i]==0) continue;
            ll x=m/v2[i];
            if(m%v2[i]) x++;
            int k=lower_bound(v2.begin()+i+1,v2.end(),x)-v2.begin();
            ans+=s2-k;
        }
        ans=(ll)n*(n-1)/2-ans;
        return ans>=k;
    }
    if(m<0)
    {
        m*=-1;
        ans+=(ll)s1*(s1-1)/2;
        ans+=(ll)s2*(s2-1)/2;
        for(int i=0;i<s1;i++)
        {
            ll x=m/v1[i];
            int k=upper_bound(v2.begin(),v2.end(),x)-v2.begin()-1;
            ans+=k+1;
        }
        ans=(ll)n*(n-1)/2-ans;
        return ans>=k;
    }
}
int main()
{
    scanf("%d%lld",&n,&k);
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        if(x<0) v1.push_back(-x);
        else v2.push_back(x);
    }
    sort(v1.begin(),v1.end());
    sort(v2.begin(),v2.end());
    ll l=-1e18,r=1e18,ans;
    while(l<=r)
    {
        ll m=l+r>>1;
        if(judge(m)) ans=m,r=m-1;
        else l=m+1;
    }
    printf("%lld\n",ans);
}

E Payment
d p i , j {dp_{i,j}} dpi,j表示第i种硬币剩余 j ( 0 < = j < = 1 ) {j}(0<=j<=1) j(0<=j<=1)个没找给我的最小价值,直接转移即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
char s[N];
ll dp[N][2];
int main()
{
    scanf("%s",s+1);
    int n=strlen(s+1);
    dp[0][1]=1000;
    for(int i=1;i<=n;i++)
    {
        int x=s[i]-'0';
        dp[i][0]=dp[i-1][0]+min(x,10-x+1);
        dp[i][0]=min(dp[i][0],dp[i-1][1]+10-x);
        dp[i][1]=min(dp[i-1][0]+10-x,dp[i-1][1]+10-x-1);
    }
    printf("%lld\n",min(dp[n][0],dp[n][1]+1));
}

F Perils in Parallel
本场最有趣的题。

首先根据坐标我们可以把问题转换为:有一个01数组a,m个操作,第i个操作为把a数组中

l i {l_{i}} li到第 r i {r_{i}} ri个元素的状态翻转,是否可以选择一系列操作,使得a数组全部为0。

构造一个数组b,使得 a i = b 1 ⨁ b 2 ⨁ . . . ⨁ b i {a_{i}=b_{1}\bigoplus b_{2}\bigoplus...\bigoplus b_{i}} ai=b1b2...bi,那么问题转换为每次选择b数组中第 l i {l_{i}} li

和第 r i + 1 {r_{i}+1} ri+1个元素进行翻转,是否可以把数组b全部翻转为0。

b数组可以这样来构造,如果 a i = = a i − 1 {a_{i}==a_{i-1}} ai==ai1 b i = 0 {b_{i}=0} bi=0(说明异或前缀和未发生改

变),否则 b i = 1 {b_{i}=1} bi=1(异或前缀和发生改变)。

对于第i个操作,我们在点 l i {l_{i}} li和点 r i + 1 {r_{i}+1} ri+1直接连一条边,那么就建成了一张图。

现在让我们考虑这张图是颗树的情况,如图:
在这里插入图片描述

那么我们可以发现,无论这个图边的形态如何,只有图中为1的点的数量有偶数个,那么一

定能把整张图的点的状态全部翻转为0。我们可以随意选择两个为1的点,将这两个点最短路

径上的边全部翻转一次,那么恰好这两个点被翻转一次,而这两个点之间的点被翻转两次,

只有这两个点的状态发生了改变。

对于整张图不是一个树的情况,因为上述结论成立,我们只要随意选择一些边,把每个连通分量

都变成一个生成树,然后分别求解每个连通分量中的答案。

那么其实还有一个疑问,对于 b n + 1 {b_{n+1}} bn+1这个元素,我们是否有必要将它也翻转为0?

首先,毫无疑问的 a n + 1 = 0 {a_{n+1}=0} an+1=0,那么将数组b全翻转为0后,有 a n {a_{n}} an一定等于0,那

么有 a n + 1 = = a n {a_{n+1}==a_{n}} an+1==an,显然b数组第n项也应该为0。

建图后就可以一遍dfs解决这个问题。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,a[N],c[N],b[N],hs[N],tot,head[N],nex[N<<1],to[N<<1],wi[N<<1];
void add(int u,int v,int w){to[++tot]=v;nex[tot]=head[u];head[u]=tot;wi[tot]=w;}
bool vis[N],use[N];
int lowb(int x)
{
    return lower_bound(hs+1,hs+1+n,x)-hs;
}
int uppb(int x)
{
    return upper_bound(hs+1,hs+1+n,x)-hs;
}
bool dfs(int u)
{
    vis[u]=true;
    int x=c[u];
    for(int i=head[u];i;i=nex[i])
    {
        int v=to[i];
        if(!vis[v]&&dfs(v))
        {
            x^=1;use[wi[i]]=true;
        }
    }
    return x;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i],&b[i]),hs[i]=a[i];
    sort(hs+1,hs+1+n);
    for(int i=1;i<=n;i++)
        a[i]=lowb(a[i]),c[a[i]]=b[i];
    for(int i=n+1;i>=1;i--)
        c[i]^=c[i-1];
    for(int i=1;i<=m;i++)
    {
        int l,r;scanf("%d%d",&l,&r);
        l=lowb(l);
        r=uppb(r)-1;
        if(l<=r)
            add(l,r+1,i),add(r+1,l,i);
    }
    for(int i=1;i<=n+1;i++)
        if(!vis[i]&&dfs(i))
    {
        printf("-1\n");return 0;
    }
    int ans=0;
    for(int i=1;i<=m;i++)
        if(use[i]) ans++;
    printf("%d\n",ans);
    for(int i=1;i<=m;i++)
    if(use[i])
        printf("%d ",i);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值