codeforces699 div2 ABC | cf699 div2 abc | 贪心,贪心,还是贪心

今日的cf题解,与总结,又因为本地的程序总被删掉,所以把调试过程也加上,作为日后回顾。

无趣的刷题才是日常,本文遵循的方法论在这篇文章中。https://www.cnblogs.com/cosmowind/p/15982590.html

 

 

A

1、概括题面:在坐标轴上,机器人初始位置为(0,0),输入一串指令UDLR,分别表示上下左右走一格。问,每个指令可以接受或执行,机器人能否走到(x,y)?

2、分析过程:
①关键词:贪心
②思路:只走能接近目标的指令,其余忽略。
③实现:统计各个指令的个数,最后判断需要的方向上的指令数是否能达到目标。
④复杂度:o(n)

3、贴个代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<=(b);i++)
#define _rp(i,b,a) for(int i=(b);i>=(a);i--)
//#define int long long
#define close std::ios::sync_with_stdio(0)

typedef long long ll;
const int N=2e5+7;

int t,a,b;
string s;
signed main(){
    cin>>t;
    while(t--){
        cin>>a>>b;
        cin>>s;
        _for(i,0,s.length()-1){
            if(a>0){
                if(s[i]=='R')a--;
            }else if(a<0){
                if(s[i]=='L')a++;
            }
            if(b>0){
                if(s[i]=='U')b--;
            }else if(b<0){
                if(s[i]=='D')b++;
            }
        }
        if(!a&&!b)cout<<"YES\n";else cout<<"NO\n";
    }
    
    
}

 

 

B(如果不是因为写博客,这题我再也不想看)

1、概括题面:n座山,分别有高度a[i]。给定k颗滚石,每颗滚石从第一座山开始向右滚,如果下一座山不高于自己,就滚到下一座山,最后滚到世界尽头;否则留在这座山,使之高度+1。问,第k颗滚石会停在哪?

2、分析过程:
①关键词:贪心、分类讨论
②思路:根据题意,在遇到一座高山时,需要把它之前的所有矮山都填到与自己同高才能通过。所以维护一个单调栈,每遇到一座比当前高的山,就把栈内所有比它低的山都拿出来填,如果k用完了,说明最后的滚石就在当前的高山以前(不包括它),栈内最顶部的元素之后(包括它),具体算法是用left_k对两者距离取模,具体实现见代码。如果遍历完所有山k>0,则输出-1。
③重要细节:当对栈里的最小元素进行填山时,应该注意到不能直接把这座山填到和高山一样的高度,因为,如果当栈内最小元素达到次小元素的大小时,同时填山的区间就会扩大,此时将最小元素退栈,用次小元素继续运行。
④复杂度:o(n)

3、贴个代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<=(b);i++)
#define _rp(i,b,a) for(int i=(b);i>=(a);i--)
//#define int long long
#define close std::ios::sync_with_stdio(0)

typedef long long ll;
const int N=2e5+7;

int t,a[N],b,s[N],bord,n,k,flag,ans,calc;
vector<int> zh;
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>k;
        s[0]=0;
        a[0]=N;
        _for(i,1,n)cin>>a[i],s[i]=s[i-1]+a[i];
        zh.clear();
        zh.push_back(0);
        zh.push_back(1);
        flag=0;ans=-1;
        _for(i,2,n){
            while(zh.size()>0&&a[zh.back()]<a[i]){
                bord=zh.back();
                if(zh.size()>1&&a[zh.back()-1]<a[i]){
                    calc=((i-bord)*a[zh.back()-1])-(s[i-1]-s[bord-1]);
                    if(calc<k){
                        k-=calc;
                        _for(j,bord,i-1)a[j]=a[zh.back()-1];
                        _for(j,1,n)s[j]=s[j-1]+a[j];
                        //cout<<k<<" "<<bord<<" "<<a[2]<<endl;
                    }else{
                        //cout<<"there\n";
                        ans=i-1-(k-1)%(i-bord);
                        //cout<<bord<<" "<<i<<" "<<a[bord]<<" "<<a[i]<<" "<<calc<<" "<<ans<<endl;
                        flag=1;
                        break;
                    }
                    zh.pop_back();
                }else{
                    calc=((i-bord)*a[i])-(s[i-1]-s[bord-1]);
                    //cout<<bord<<" "<<i<<" "<<a[bord]<<" "<<a[i]<<" "<<calc<<" "<<ans<<endl;
                    if(calc<k){
                        k-=calc;
                        _for(j,bord,i-1)a[j]=a[i];
                        _for(j,1,n)s[j]=s[j-1]+a[j];
                        //cout<<k<<" "<<bord<<" "<<a[2]<<endl;
                    }else{
                        //cout<<"there\n";
                        ans=i-1-(k-1)%(i-bord);
                        //cout<<bord<<" "<<i<<" "<<a[bord]<<" "<<a[i]<<" "<<calc<<" "<<ans<<endl;
                        flag=1;
                        break;
                    }
                }
            }
            if(a[i]<a[zh.back()])zh.push_back(i);
            //zh.push_back(i);
            if(flag)break;
            /*
            cout<<"look "<<zh.size()<<" "<<zh.back()<<endl;
            _for(j,0,zh.size()-1)cout<<zh[j]<<" ";cout<<endl;
            _for(j,0,zh.size()-1)cout<<a[zh[j]]<<" ";cout<<endl;
            */
        }
        if(flag)cout<<ans<<endl;else cout<<-1<<endl;
    }
    
    
}
/*

1
12 172
60 7 60 49 5 80 1 78 41 9 57 65

25 2114
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 100



*/

 

 

C

1、概括题面:n个栅栏,原有颜色a[i],目标颜色b[i],先后请来m个粉刷匠,只能给1个栅栏上色为c[i]。问,能否达到目标?粉刷匠分别给哪个栅栏上色?

2、分析过程:产生做法的思路过程,总体说解题算法的关键词,某某数据结构,dp状态之类的。对一些重要的细节,讨论的过程进行具体阐述。最后分析复杂度。
①关键词:贪心(除了贪心不知道怎么描述)
②思路:首先倒着枚举粉刷匠,因为越靠后的粉刷匠越不会被其它颜色遮盖。对于每个粉刷匠,做三个判断:(1)对应的颜色还有没有需要涂的?qu[c[i]]>0?【进行上色任务】(2)目标颜色b[i]中是否有c[i]这个颜色?【无需该色,找个不做负面影响的地方】(3)该粉刷匠是否为倒数第一个粉刷匠?如果是最后的粉刷匠,又没有对目标做贡献,也没有相同颜色存放自己,那就只能破坏计划,直接输出 NO。
③重要细节:为执行以上功能,我们需要预处理出相应的数组。qu[i]表示颜色i需要用在第qu[i]个栅栏上;last[i]表示与位置i上颜色相同且也需要上色的上一个位置在哪,若没有则为0;
④复杂度:o(n)

3、贴个代码:代码中还有其它的优化,实际上不要也罢。比如,统计粉刷匠能提供的颜色数以及某种颜色需要的个数,若前者较小,则失败。

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<=(b);i++)
#define _rp(i,b,a) for(int i=(b);i>=(a);i--)
//#define int long long
#define close std::ios::sync_with_stdio(0)
#define mst(f,a) memset(f,a,sizeof(f));
#define die cout<<"NO\n";return
typedef long long ll;
const int N=1e5+7;

int n,m,t,a[N],b[N],c[N],qu[N],last[N],cnt_lai[N],cnt_que[N],wri[N],po[N];
string s;

void solve(){
    cin>>n>>m;
    mst(last,0);
    mst(qu,0);
    mst(cnt_lai,0);
    mst(cnt_que,0);
    mst(wri,0);
    mst(po,0);
    _for(i,1,n)cin>>a[i];
    _for(i,1,n)cin>>b[i];
    _for(i,1,m)cin>>c[i],cnt_lai[c[i]]++;
    _for(i,1,n){
        if(a[i]!=b[i]){
            cnt_que[b[i]]++;
            //if(qu[b[i]]){
                last[i]=qu[b[i]];
                qu[b[i]]=i;
                //cout<<b[i]<<" "<<a[i]<<" "<<i<<" "<<qu[b[i]]<<endl;
            //}
            if(cnt_lai[b[i]]<cnt_que[b[i]]){
                die;
            }
        }
        po[b[i]]=i;
    }
    //cout<<"there\n";
    _rp(i,m,1){
        //cout<<" "<<i<<" "<<t<<endl;
        if(qu[c[i]]>0){
            wri[i]=qu[c[i]];
            qu[c[i]]=last[qu[c[i]]];
            //cout<<"__ "<<i<<" "<<t<<" "<<wri[i]<<" "<<qu[c[i]]<<endl;
        }else if(po[c[i]]>0){
            wri[i]=po[c[i]];
            //cout<<"++ "<<i<<" "<<t<<endl;
        }else if(i<m){
            wri[i]=wri[m];
            //cout<<"33 "<<i<<" "<<t<<endl;
        }else{
            die;
        }
    }
    _for(i,1,n){
        if(qu[i]){
            die;
        }
    }
    cout<<"YES\n";
    _for(i,1,m){
        cout<<wri[i]<<" ";
        a[wri[i]]=c[i];
    }
    cout<<endl;/*
    _for(i,1,n){
        cout<<a[i]<<" ";
    }
    cout<<endl;
    */
}

signed main(){
    close;
    cin>>t;
    while(t--){
        solve();
    }
}
/*
1
27 24
21 18 18 23 17 8 7 21 12 10 3 13 5 16 3 17 7 27 20 18 2 5 3 26 22 24 2
15 9 18 23 17 8 7 21 12 10 3 13 5 16 3 17 13 27 22 18 2 5 3 25 22 24 2
22 9 27 15 7 20 7 9 6 27 11 1 11 23 12 25 19 22 9 15 11 13 5 9




*/

 

posted @ 2022-03-10 11:14  windiest  阅读(38)  评论(0编辑  收藏  举报