Codeforces Round #693 (Div. 3)题解

题目链接:Dashboard - Codeforces Round #693 (Div. 3) - Codeforces

A. Cards for Friends

题意:给定长为n,宽为m的一张纸片;纸片长或宽为偶数时可被裁剪为相同的新的两张纸片,则原纸片能否至少被裁剪为k张。

思路:剪就是了。

代码:

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        ll w,h;
        cin>>w>>h>>n;
        ll sum=1;
        while(w%2==0)
        {
            sum*=2;
            w/=2;
        }
        while(h%2==0)
        {
            sum*=2;
            h/=2;
        }
        if(sum>=n)yes;
        else no;
    }
}
View Code

B. Fair Division

题意:给定n颗糖果,糖果权值是1或2,能否将糖果分为两部分使得两部分各总权值相等。

思路:若权值为1糖果数量为奇,则总权值为奇,一定不可平分。若权值为1糖果数量为偶,考虑权值为2糖果数量;若为偶,则全部平分,若为奇,则在平分后多出1颗,至少需要两颗权值为1糖果补足。

代码:

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        cin>>n;
        ll sum1=0,sum2=0;
        rep(i,1,n)
        {
            ll x;
            cin>>x;
            if(x==1)sum1++;
            else sum2++;
        }
        if(sum1%2)no;
        else
        {
            if(sum2%2&&sum1<2)no;
            else yes;
        }
    }
}
View Code
C. Long Jumps
题意:给定n个数,定义操作为选定下标i,得分P=a[i]+a[i+a[i]]+a[i+a[i]+a[i+a[i]]]+……,下标大于n时结束。求一次操作的最大得分。
思路:记忆化搜索,直接递归。
代码:
ll F(ll x)
{
    if(x>n)return 0;
    if(dp[x]!=-1)return dp[x];
    dp[x]=F(x+a[x])+a[x];
    return dp[x];
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        mem(dp,-1);
        cin>>n;
        rep(i,1,n)cin>>a[i];
        ll maxn=-1;
        rep(i,1,n)maxn=max(maxn,F(i));
        cout<<maxn<<endl;
    }
}
View Code

D. Even-Odd Game

题意:给定n个数,Alice和Bob轮流操作,不能不操作,Alice先手。Alice选择偶数时得分增加a[i],奇数不加分;Bob选择奇数时得分增加a[i],偶数不加分。

双方选择最优方案,询问结果。

思路:加分最优拿最大,不加分最优拿最大。

代码:

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        cin>>n;
        ll bob=0,alice=0;
        rep(i,1,n)cin>>a[i];
        sort(a+1,a+1+n,greater<ll>());
        rep(i,1,n)
        {
            if(i%2==1)
            {
                if(a[i]%2==0)alice+=a[i];
            }
            else
            {
                if(a[i]%2==1)bob+=a[i];
            }
        }
        if(alice>bob)cout<<"Alice"<<endl;
        else if(alice<bob)cout<<"Bob"<<endl;
        else cout<<"Tie"<<endl;
    }
}
View Code

E. Correct Placement

题意:Problem - E - Codeforces

思路:贪心排序,阅读理解……

代码:

struct node
{
    ll h,w,n,ans;
}a[N];
bool cmp1(node a,node b)
{
    if(a.h==b.h)return a.w>b.w;
    return a.h<b.h;
}
bool cmp2(node a,node b)
{
    return a.n<b.n;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        cin>>n;
        rep(i,0,n-1)
        {
            cin>>a[i].h>>a[i].w;
            a[i].n=i;
            a[i].ans=-1;
            if(a[i].h>a[i].w)swap(a[i].h,a[i].w);
        }
        sort(a,a+n,cmp1);
        ll minn=0;
        rep(i,1,n-1)
        {
            if(a[i].w>a[minn].w)a[i].ans=a[minn].n+1;
            if(a[i].w<a[minn].w)minn=i;
        }
        sort(a,a+n,cmp2);
        rep(i,0,n-1)cout<<a[i].ans<<" ";
        cout<<endl;
    }
}
View Code

F. New Year's Puzzle(补)

题意:给定一个n*2的长方形,其中m个格子已经被填充,给出mge格子的坐标,剩下的部分能否被1*2的骨牌(可旋转)填满。

思路:从左向右递推,根据情况分类模拟(其实还挺有意思的

代码:

struct node
{
    ll x,y;
}a[N];
bool cmp(node a,node b)
{
    if(a.y==b.y)return a.x<b.x;
    return a.y<b.y;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        rep(i,1,m)cin>>a[i].x>>a[i].y;
        sort(a+1,a+1+m,cmp);
        ll up=0,down=0,flag=1;
        a[m+1].y=0;
        rep(i,1,m)
        {
            ll upp=a[i].y-up-1;
            ll downn=a[i].y-down-1;
            if(a[i].y==a[i+1].y)
            {
                if(upp==downn)
                {
                    up=a[i].y;
                    down=a[i].y;
                }
                else flag=0;
                i++;
            }
            else if(a[i].x==1)
            {
                if(up==down)
                {
                    up=a[i].y;
                    down=a[i].y-1;
                }
                else
                {
                    if(upp%2==0)
                    {
                        up=a[i].y;
                        down=a[i].y;
                    }
                    else flag=0;
                }
            }
            else
            {
                if(up==down)
                {
                    up=a[i].y-1;
                    down=a[i].y;
                }
                else
                {
                    if(downn%2==0)
                    {
                        up=a[i].y;
                        down=a[i].y;
                    }
                    else flag=0;
                }
            }
        }
        if(up!=down)flag=0;
        if(flag)yes;
        else no;
    }
}
View Code

G. Moving to the Capital

题意:给定一张有向图,定义点权为距离点1的最短距离,定义两种操作,第一种为从点i到沿路径到点j且d[i]<d[j],第二种为d[i]>=d[j];其中第二种操作至多使用1次,询问每个点到点1所需的最小操作次数。

思路:先跑一次dijkstra求权值,然后标记两种线段跑dfs(记忆化搜索)

代码:

vector<ll>vec[N],c[N];
void dijkstra(ll tt)
{
    queue<ll>q;
    dis[tt]=0;
    vis[tt]=1;
    q.push(tt);
    while(!q.empty())
    {N
        ll u=q.front();
        q.pop();
        c[dis[u]].push_back(u);
        ll len=vec[u].size();
        rep(i,0,len-1)
        {
            ll v=vec[u][i];
            if(vis[v])continue;
            dis[v]=dis[u]+1;
            vis[v]=1;
            q.push(v);
        }
    }
}
/*ll dfs(ll k,ll flag)
{
    if (dp[k][flag]!=1e6) return dp[k][flag];
    else {dp[k][flag]=dis[k];
    for(auto v:vec[k])
    {
        if(dis[v]>dis[k])
        {
            dp[k][flag]=min(dp[k][flag],dfs(v,flag));
        }
        else
        {
            if(!flag)dp[k][flag]=min(dp[k][flag],dfs(v,1));
        }
    }
    return dp[k][flag];}
}*/
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    //IO
    cin>>t;
    while(t--)
    {
        mem(vis,0);
        rep(i,1,n)
        {
            vec[i].clear();
            c[i].clear();
        }
        cin>>n>>m;
        rep(i,1,m)
        {
            cin>>u>>v;
            vec[u].push_back(v);
        }
        dijkstra(1);
        rep(i,1,n)f[i]=dis[i];
        per(l,n-1,1)
        {
            ll num=c[l].size();
            rep(i,0,num-1)
            {
                ll u=c[l][i],len=vec[u].size();
                rep(j,0,len-1)
                {
                    ll v=vec[u][j];
                    if(dis[u]<dis[v])f[u]=min(f[u],f[v]);
                    else f[u]=min(f[u],dis[v]);
                }
            }
        }
        rep(i,1,n)cout<<f[i]<<" ";
        cout<<endl;
    }
}
View Code

 

 

posted @ 2021-06-03 15:01  Geospiza  阅读(63)  评论(0)    收藏  举报