AtCoder Beginner Contest 176


ABCDEF

( √:做出; ●:尝试未做出; ○:已补题 )


题目地址:https://atcoder.jp/contests/abc176



A Takoyaki

题意:签到题

思路

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

int main()
{
    int n=read(),x=read(),t=read();
    if(n%x==0) cout<<n/x*t;
    else cout<<(n/x+1)*t;

    return 0;
}



B Multiple of 9

题意:签到题

思路

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

char s[1000005];

int main()
{
    scanf("%s",s);
    int a=0;
    for(int i=0;s[i];i++) a+=s[i]-'0';
    puts(a%9==0?"Yes":"No");

    return 0;
}



C Step

题意:签到题

思路

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=2e5+5;
int a[maxn];

int main()
{
    int n=read();
    REP(i,1,n) a[i]=read();
    LL ans=0;
    REP(i,2,n) if(a[i]<a[i-1]) ans+=a[i-1]-a[i],a[i]=a[i-1];
    cout<<ans;

    return 0;
}



D Wizard in Maze

题意:一张 n*m 的地图( 1 ≤ n , m ≤ 1 0 3 1\le n,m\le 10^3 1n,m103),上面有空地和墙。你一开始在一个点,目标是另一个点,你可以往上下左右相邻的结点走,但是只能走空地,你也可以用魔法跳到以当前点为中心,5*5的范围内的任意空地。要求出走到目标点使用魔法的最少次数。

思路:典型的01BFS。用双端队列维护候选结点,对于当前结点,首先走上下左右,如果可以走并且没有标记过,就加入队首;然后使用魔法,如果可以跳到某个空地并且没有标记,那么把这个点加入队尾。这样保证每次从队首取出来的点到达它使用的魔法数一定是最少的。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=1e3+5;
char s[maxn][maxn];
int ans[maxn][maxn],vis[maxn][maxn],n,m,fx,fy,tx,ty;
int dir[4][2]={1,0,-1,0,0,1,0,-1};

struct node
{
    int x,y,step=0;
};
deque<node> Q;

int main()
{
    n=read(),m=read();
    fx=read(),fy=read();
    tx=read(),ty=read();
    REP(i,1,n) scanf("%s",s[i]+1);
    REP(i,1,n) REP(j,1,m) ans[i][j]=-1;
    Q.push_back((node){fx,fy,0});
    while(!Q.empty())
    {
        node nd=Q.front(); Q.pop_front();
        int x=nd.x,y=nd.y,step=nd.step;
        if(vis[x][y]) continue;
        //cout<<x<<' '<<y<<endl;
        vis[x][y]=1;
        ans[x][y]=step;
        for(int i=0;i<4;i++)
        {
            int xx=x+dir[i][0],yy=y+dir[i][1];
            if(xx>0 && xx<=n && yy>0 && yy<=m && !vis[xx][yy] && s[xx][yy]=='.')
                Q.push_front((node){xx,yy,step});
        }
        for(int xx=x-2;xx<=x+2;xx++)
            for(int yy=y-2;yy<=y+2;yy++)
            {
                if(xx>0 && xx<=n && yy>0 && yy<=m && !vis[xx][yy] && s[xx][yy]=='.')
                    Q.push_back((node){xx,yy,step+1});
            }
    }
    if(ans[tx][ty]<0) puts("-1");
    else printf("%d\n",ans[tx][ty]);

    return 0;
}



E Bomber

题意:有一个 n*m( 1 ≤ n , m ≤ 3 × 1 0 5 1\le n,m \le 3\times 10^5 1n,m3×105)大小的矩阵,上面有 M 个目标点,你要选择一个点安置炸药,这个炸药可以炸毁同一行同一列的所有格子,要求出最多能炸毁多少目标点。

思路:安放位置一定是目标最多的列和目标最多的行的交点,如果所有这样的交点中,存在一个交点不是目标点,那么答案就是这一行和这一列的目标数之和;如果这些交点中全部都是目标点,那么答案就是目标数之和减一。因为目标点总数不会超过 M,所以直接枚举这些交点,找到不是目标点的跳出就行了。

代码

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=3e5+5;
int nx[maxn],ny[maxn],n,m,N;
P xx[maxn],yy[maxn];
set<P> s;

int main()
{
    n=read(),m=read(); N=read();
    REP(i,1,N)
    {
        int x=read(),y=read();
        nx[x]++; ny[y]++;
        s.insert(P(x,y));
    }
    REP(i,1,n) xx[i]=P(nx[i],i);
    REP(i,1,m) yy[i]=P(ny[i],i);
    sort(xx+1,xx+n+1,greater<P>());
    sort(yy+1,yy+m+1,greater<P>());

    int maxx=xx[1].first,maxy=yy[1].first,flag=0;
    for(int i=1;xx[i].first==maxx;i++)
    {
        if(flag) break;
        for(int j=1;yy[j].first==maxy;j++)
        {
            if(!s.count(P(xx[i].second,yy[j].second)))
            {
                flag=1;
                break;
            }
        }
    }
    int ans=xx[1].first+yy[1].first;
    if(flag) cout<<ans;
    else cout<<ans-1;

    return 0;
}



F Brave CHAIN

题意:给你 3n 张卡片,你每次从前五张中选择三张扔掉,如果这三张都相同,就 +1 分 。卡片上的数字范围在 1

-n 之间。问最多可以得多少分。

思路:迷之 dp 。还是看题解的转移吧:

代码

代码就是根据题解的各种转移来写的。

#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
    int x=0,flag=1; char c=getchar();
    while((c>'9' || c<'0') && c!='-') c=getchar();
    if(c=='-') flag=0,c=getchar();
    while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return flag?x:-x;
}

const int maxn=2005;
int n,a[maxn<<2],f[maxn][maxn],maxd[maxn];
struct node {int x,y,z;} que[maxn*maxn];
int tail,maxx,extadd;

void add(int x,int y,int z)
{
    que[++tail]=(node){x,y,z};
}

void update()
{
    for(int i=1;i<=tail;i++)
    {
        node d=que[i];
        f[d.x][d.y]=max(f[d.x][d.y],d.z);
        f[d.y][d.x]=max(f[d.y][d.x],d.z);
        maxx=max(maxx,d.z);
        maxd[d.x]=max(maxd[d.x],d.z);
        maxd[d.y]=max(maxd[d.y],d.z);
    }
    tail=0;
}

int main()
{
    n=read();
    REP(i,1,n*3) a[i]=read();

    REP(i,1,n) REP(j,1,n) f[i][j]=-10000000;
    REP(i,1,n) maxd[i]=-100000000;
    f[a[1]][a[2]]=f[a[2]][a[1]]=0;
    maxd[a[1]]=maxd[a[2]]=0;

    for(int i=1;i<n;i++)
    {
        if(a[i*3]==a[i*3+1] && a[i*3]==a[i*3+2])
        {
            extadd++;
            continue;
        }
        if(a[i*3]==a[i*3+1] || a[i*3]==a[i*3+2] || a[i*3+1]==a[i*3+2])
        {
            int p=a[i*3],q=a[i*3+1];
            if(p==q) q=a[i*3+2];
            else if(a[i*3+2]==q) swap(p,q);
            for(int k=1;k<=n;k++)
                add(k,q,f[k][p]+1);
        }

        {
            int p=a[i*3],q=a[i*3+1],r=a[i*3+2];
            add(q,r,f[p][p]+1);
            add(q,p,f[r][r]+1);
            add(p,r,f[q][q]+1);
        }

        int p=a[i*3],q=a[i*3+1],r=a[i*3+2];
        add(p,q,maxx);
        add(p,r,maxx);
        add(q,r,maxx);

        REP(j,0,2)
        {
            int p=a[i*3+j];
            for(int k=1;k<=n;k++)
                add(k,p,maxd[k]);
        }

        update();
        //REP(i,1,n) REP(j,1,n) cout<<f[i][j]<<' ';
        //cout<<endl<<endl;
    }
    REP(i,1,n) REP(j,1,n) maxx=max(maxx,f[i][j]);
    maxx=max(maxx,f[a[n*3]][a[n*3]]+1);
    cout<<maxx+extadd;

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值