AtCoder Beginner Contest 352

目录

A - AtCoder Line

题意:

代码:

B - Typing

题意:

代码:

C - Standing On The Shoulders

题意:

代码:

D - Permutation Subsequence 

题意:

思路:

代码:   


A - AtCoder Line

题意:

        有n站列车,列车从x站开往y站,需要在z站上车。如果能,输出Yes,反之,输出No。

代码:

//AtCoder Beginner Contest 352
//A - AtCoder Line
//https://atcoder.jp/contests/abc352/tasks/abc352_a
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int n,x,y,z;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>x>>y>>z;
    if(x>y)
        swap(x,y);
    if(x<z&&y>z)
        cout<<"Yes"<<endl;
    else
        cout<<"No"<<endl;
    return 0;
}

B - Typing

题意:

        有字符串 s 和字符串 t ,在 t 中找到字符串 s 中字符的位置,并输出。

        注意:下标从1开始。

代码:

//AtCoder Beginner Contest 352
//B - Typing
//https://atcoder.jp/contests/abc352/tasks/abc352_b
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=2e5+5;
string s,t;
int pos[N];
int p=0;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>s>>t;
    int lens=s.length();
    int lent=t.length();
    int j=0;
    for(int i=0;i<lens;i++){
        while(t[j++]!=s[i])
            ;
        pos[p++]=j;
    }
    for(int i=0;i<p;i++){
        cout<<pos[i];
        if(i!=p-1)
            cout<<" ";
    }
    return 0;
}

C - Standing On The Shoulders

题意:

        有n个巨人,堆叠在一起。堆叠的规则是:从地面开始,除了第一个巨人脚踩地面,其余巨人踩着下面巨人的肩膀。求最后一个巨人,头顶距离地面的距离最大值。

思路:

        将n个巨人的头长度进行从小到大排序,每个巨人之间踩着肩膀,所以身高在相加的时候无需考虑,只需要找到最大头的那个巨人即可。答案就是:sum=所有巨人的高度肩高+最大头的头的高。

代码:

//AtCoder Beginner Contest 352
//C - Standing On The Shoulders
//https://atcoder.jp/contests/abc352/tasks/abc352_c
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
typedef struct Giant{
    int shoulder;
    int height;
    int cha;
}Giant;
const int N=2e5+5;
int n;
ll sum=0;
Giant giant[N];
bool cmp(Giant a,Giant b){
    if(a.cha<b.cha)
        return true;
    return false;
}
void Cin(){
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>giant[i].shoulder>>giant[i].height;
}
void Init(){
    for(int i=0;i<n;i++){
        giant[i].cha=giant[i].height-giant[i].shoulder;
    }
}
void Sort(){
    sort(giant,giant+n,cmp);
}
void Solve(){
    for(int i=0;i<n;i++){
        sum+=giant[i].shoulder;
    }
    sum+=giant[n-1].cha;
    cout<<sum<<endl;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    Cin();
    Init();
    Sort();
    Solve();
    return 0;
}

D - Permutation Subsequence 

题意:

        给定一个数组,数组的下标从1开始,这些数通过排列,可以变成公差为1的等差数列,求排序之后,在区间大小为k的范围内,找到最大的下标和最小的下标之差。

思路:

        将数组进行排序后,找个有多少个等差数列,题目要求区间大小为k,则使用滑动窗口来求解。滑动窗口求解最大值和最小值。

代码:   

//AtCoder Beginner Contest 352
//D - Permutation Subsequence
//https://atcoder.jp/contests/abc352/tasks/abc352_d
//Time Limit: 2 sec
//Memory Limit: 1024 MB
//
#include <bits/stdc++.h>

using namespace std;
const int N=1e5+5;
int n,k,cc;
int answer[N];//存储 每个队列的最小答案
bool cmp(pair<int ,int >a,pair<int , int >b){
    if(a.first<b.first)
        return true;
    return false;
}
void Mypopmax(deque<int> &que,int value){ 
	if(!que.empty() &&value == que.front()){ //当队首元素等于要上个区间的头部时 删除
		que.pop_front();
	}
}
void Mypushmax(deque<int> &que,int value){ //
	while(!que.empty() && value > que.back()){ //循环:如果当前元素大于队尾,则队尾元素失效了
		que.pop_back();
	}
	que.push_back(value);
}
void Mypopmin(deque<int> &que,int value){ 
	if(!que.empty() &&value == que.front()){
		que.pop_front();
	}
}
void Mypushmin(deque<int> &que,int value){
	while(!que.empty() && value < que.back() ){
		que.pop_back();
	}
	que.push_back(value);
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>k;
    vector< pair<int ,int > >start_vec;// start_vec记录原始输入的数据。
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        start_vec.push_back({x,i});
    }
    sort(start_vec.begin(),start_vec.end(),cmp); //将start_vec以自定义cmp的方式进行排序。
                                                //即按照 点的第一值进行快速排序。
    /*for(int i=0;i<n;i++){
        cout<<vec[i].first<<" "<<vec[i].second<<endl;
    }*/
    vector<pair<int ,int > >ans; // ans 用来临时储存公差为1的等差数列
    vector< vector< pair<int ,int> > >vs; // vs 来储存 公差为1的等差数列。
    ans.push_back(start_vec[0]);// 将第一个元素添加到ans里面。
    int nums=0,j=0; // nums统计有多少组公差为1的等差数列。 j是ans储存时的下标。
    for(int i=1;i<n;i++){
        if(start_vec[i].first-ans[j].first==1){ //满足公差为1
            ans.push_back(start_vec[i]); // 将 start_vec[i] 添加到 ans去。
            j++; // start_vec[i] 的位置即为 j++。用于与下一个数据进行判断等差数列。
        }
        else{ //不满足公差为1
            vs.push_back(ans); //将ans添加到 vs里去。
            nums++; // 数列 数加1。
            ans.clear();//清空ans
            ans.push_back(start_vec[i]);// 将当前元素作为下一个数列的首项
            j=0;//队首下标从0开始
        }
    }
    vs.push_back(ans);// 扫尾
    nums++;// 数列 数加1。
    for(int ii=0;ii<nums;ii++){ //遍历 vs
        vector< pair<int ,int > >vec=vs[ii]; //vec 表示当前队列。

        int vec_size=vec.size();// vec_size 表示 队列的长度。

        if(vec_size<k)// 如果队列长度<滑动窗口长度,直接跳到下一个队列。
            continue;
        deque<int>que;
        vector<int>maxresult;
        int maxx=vec[0].second;
        que.push_back(maxx);
        for (int i = 1;i < k; i++) { // 先将前k的元素放进队列
                maxx=maxx<vec[i].second?vec[i].second:maxx;
                while(!que.empty()&&que.front()<vec[i].second){ //如果当前元素大于队首,则队首元素失效了
                    que.pop_front();                           //弹出队首元素。
                }
                while(!que.empty()&&que.back()<vec[i].second){ //如果当前元素大于队尾,则队尾元素失效了
                    que.pop_back();                           //弹出队尾部元素。
                }
                que.push_back(vec[i].second); //当前元素进队。
                //que.push_back(vec[i].second);
        }
        maxresult.push_back(maxx); // maxresult 记录前k的元素的最大值
        for (int i = k; i < vec_size; i++) {
            Mypopmax(que,vec[i-k].second);; // 滑动窗口移除最前面元素
            Mypushmax(que,vec[i].second);// 滑动窗口前加入最后面的元素
            maxresult.push_back(que.front()); // 记录对应的最大值
            /*cout<<que.front()<<" ";*/
        }

        deque<int>qu;
        vector<int>minresult;
        int minn=vec[0].second;
        qu.push_back(minn);
        for (int i = 1;i < k; i++) { // 先将前k的元素放进队列
                    minn=minn>vec[i].second?vec[i].second:minn;
                    while(!qu.empty()&&qu.front()>vec[i].second){ //如果当前元素小于队首,则队首元素失效了
                        qu.pop_front();                          //弹出队首元素
                    }
                    while(!qu.empty()&&qu.back()>vec[i].second){ //如果当前元素小于队尾,则队尾元素失效了
                        qu.pop_back();                          //弹出队尾元素
                    }
                    qu.push_back(vec[i].second);
        }
        minresult.push_back(minn); // minresult 记录前k的元素的最小值
        for (int i = k; i < vec_size; i++) {
            Mypopmin(qu,vec[i-k].second);; // 滑动窗口移除最前面元素
            Mypushmin(qu,vec[i].second);// 滑动窗口前加入最后面的元素
            minresult.push_back(qu.front()); // 记录对应的最小值
            /*cout<<qu.front()<<" ";*/
        }
        //cout<<endl;

        int sizee=minresult.size(); //记录滑动窗口的个数
        /*cout<<"maxresult"<<endl;
        for(int i=0;i<sizee;i++){
                cout<<maxresult[i]<<endl;
            }
        cout<<"minresult"<<endl;
        for(int i=0;i<sizee;i++){
                cout<<minresult[i]<<endl;
            }*/

        vector<int>result; //保存对于同一滑动窗口,最大值与最小值之差的结果。
        for(int i=0;i<sizee;i++){
            result.push_back(maxresult[i]-minresult[i]);
        }
        sort(result.begin(),result.end());
        answer[cc++]=result[0];// 存储每个队列的答案 并记录数量cc++。
    }
    sort(answer,answer+cc);// 对answer答案进行从小到大快速排序
    cout<<answer[0]<<endl;// answer[0]即为结果,输出。
    return 0;
}

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值