头像

weixiao




离线:5天前



weixiao
5天前

题目描述

有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。

您只能在窗口中看到k个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为[1 3 -1 -3 5 3 6 7],k为3。
Dingtalk_20201017230538.jpg
您的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数n和k,分别代表数组长度和滑动窗口的长度。

第二行有n个整数,代表数组的具体数值。

同行数据之间用空格隔开。

输出格式

输出包含两个。

第一行输出,从左至右,每个位置滑动窗口中的最小值。

第二行输出,从左至右,每个位置滑动窗口中的最大值。

数据范围

1≤n≤$10^6$

输入样例

8 3
1 3 -1 -3 5 3 6 7

输出样例

-1 -3 -3 -3 3 3
3 3 5 5 6 7

C++ 代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=1000010;
int a[N],q[N];//a[]是原数组,q[]是单调队列
int n,k;
int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++) cin>>a[i];
    int hh=0,tt=-1;
    for(int i=0;i<n;i++){
        if(hh<=tt && q[hh]<i-k+1) hh++;//如果队列不空,并且原队头元素已不在当前滑动窗口内,删去
        while(hh<=tt && a[q[tt]]>=a[i]) tt--;//如果队列不空,并且队尾元素>=当前元素,在取最小值时不用考虑,删去;剩下的元素单调递增
        q[++tt]=i;//将该元素下标加入队列
        if(i>=k-1) cout<<a[q[hh]]<<" ";//如果i在窗口内,输出队头元素,即最小值
    }
    puts("");
    hh=0,tt=-1;
    for(int i=0;i<n;i++){//最大值思路一样
        if(hh<=tt && q[hh]<i-k+1) hh++;
        while(hh<=tt && a[q[tt]]<=a[i]) tt--;
        q[++tt]=i;
        if(i>=k-1) cout<<a[q[hh]]<<" ";
    }
    return 0;
}



weixiao
8天前

题目描述

给定一个长度为N的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出-1。

输入格式

第一行包含整数N,表示数列长度。

第二行包含N个整数,表示整数数列。

输出格式

共一行,包含N个整数,其中第i个数表示第i个数的左边第一个比它小的数,如果不存在则输出-1。

数据范围

1≤N≤$10^5$
1≤数列中元素≤$10^9$
所有操作保证合法。

输入样例

5
3 4 2 7 5

输出样例

-1 3 -1 2 2

C++ 代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=100010;
int stk[N],tt;
int main(){
    int m;
    cin>>m;
    for(int i=0;i<m;i++){
        int x;
        cin>>x;
        while(tt && stk[tt]>=x) tt--;//当栈不空且栈顶元素>=当前数时,这个栈顶元素在后面检索其他数时被当前数代替,所以删去
        if(tt) cout<<stk[tt]<<" ";
        else cout<<"-1 ";
        stk[++tt]=x;
    }
    return 0;
}



weixiao
1个月前

题目描述

实现一个队列,队列初始为空,支持四种操作:

(1) “push x” – 向队尾插入一个数x;

(2) “pop” – 从队头弹出一个数;

(3) “empty” – 判断队列是否为空;

(4) “query” – 查询队头元素。

现在要对队列进行M个操作,其中的每个操作3和操作4都要输出相应的结果。

输入格式

第一行包含整数M,表示操作次数。

接下来M行,每行包含一个操作命令,操作命令为”push x”,”pop”,”empty”,”query”中的一种。

输出格式

对于每个”empty”和”query”操作都要输出一个查询结果,每个结果占一行。

其中,”empty”操作的查询结果为“YES”或“NO”,”query”操作的查询结果为一个整数,表示队头元素的值。

数据范围

1≤M≤100000,
1≤x≤$10^9$,
所有操作保证合法。

输入样例

10
push 6
empty
query
pop
empty
push 3
push 4
pop
query
push 6

输出样例

NO
6
YES
4

C++ 代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=100010;
int q[N],hh,tt;//q表示队列,hh表示队头指针,tt表示队尾指针
int main(){
    int m;//m个操作
    cin>>m;
    while(m--){
        string op;
        cin>>op;
        if(op=="push"){
            int x;
            cin>>x;
            q[tt++]=x;//从队尾插入元素
        }
        else if(op=="pop") hh++;//从队头弹出一个元素,即头指针++
        else if(op=="empty"){
            if(hh<tt) cout<<"NO"<<endl;//如果头指针在尾指针前面,说明队列中有元素,不空
            else cout<<"YES"<<endl;
        }
        else{
            cout<<q[hh]<<endl;//访问队头元素
        }
    }
    return 0;
}



weixiao
1个月前

题目描述

实现一个栈,栈初始为空,支持四种操作:

(1) “push x” – 向栈顶插入一个数x;

(2) “pop” – 从栈顶弹出一个数;

(3) “empty” – 判断栈是否为空;

(4) “query” – 查询栈顶元素。

现在要对栈进行M个操作,其中的每个操作3和操作4都要输出相应的结果。

输入格式

第一行包含整数M,表示操作次数。

接下来M行,每行包含一个操作命令,操作命令为”push x”,”pop”,”empty”,”query”中的一种。

输出格式

对于每个”empty”和”query”操作都要输出一个查询结果,每个结果占一行。

其中,”empty”操作的查询结果为“YES”或“NO”,”query”操作的查询结果为一个整数,表示栈顶元素的值。

数据范围

1≤M≤100000,
1≤x≤$10^9$
所有操作保证合法。

输入样例

10
push 5
query
push 6
pop
query
pop
empty
push 4
query
empty

输出样例

5
5
YES
4
NO

C++ 代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=100010;
int stk[N],tt;//stk是栈,tt是栈顶指针
int main(){
    int m;//m个操作
    cin>>m;
    while(m--){
        string op;
        cin>>op;
        if(op=="push"){
            int x;
            cin>>x;
            stk[++tt]=x;//插入元素
        }
        else if(op=="pop") tt--;//删除元素
        else if(op=="empty"){
            if(tt>0) cout<<"NO"<<endl;//如果栈顶指针>0说明栈不空
            else cout<<"YES"<<endl;
        }
        else{
            cout<<stk[tt]<<endl;//访问栈顶元素
        }
    }
    return 0;
}



weixiao
1个月前

题目描述

给定两个正整数,计算它们的差,计算结果可能为负数。

输入格式

共两行,每行包含一个整数。

输出格式

共一行,包含所求的差。

数据范围

1≤整数长度≤$10^5$

输入样例

32
11

输出样例

21

C++ 代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
bool cmp(vector<int> &a,vector<int> &b){
    if(a.size()!=b.size()) return a.size()>b.size();
    for(int i=a.size()-1;i>=0;i--){
        if(a[i]!=b[i]) return a[i]>b[i];
    }
    return true;
}
vector<int> sub(vector<int> &a,vector<int> &b){
    vector<int> c;
    int t=0;//借位
    for(int i=0;i<a.size();i++){
        t=a[i]-t;//原本是t=a[i]-b[i]-t,但是要判断一下b有没有这一位
        if(i<b.size()) t-=b[i];
        c.push_back((t+10)%10);//两种情况综合:(1)t>=0 (t+10)%10=t%10 (2)t<0 (t+10)%10
        if(t<0) t=1;//有借位
        else t=0;
    }
    while(c.size()>1 && c.back()==0) c.pop_back();//去前导0
    return c;
}
int main(){
    string a,b;
    vector<int> A,B,c;
    cin>>a>>b;
    for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
    if(cmp(A,B)){
        c=sub(A,B);
        for(int i=c.size()-1;i>=0;i--) cout<<c[i];
    }
    else{
        c=sub(B,A);
        cout<<"-";
        for(int i=c.size()-1;i>=0;i--) cout<<c[i];
    }
    return 0;
}



weixiao
1个月前

题目描述

实现一个双链表,双链表初始为空,支持5种操作:

(1) 在最左侧插入一个数;

(2) 在最右侧插入一个数;

(3) 将第k个插入的数删除;

(4) 在第k个插入的数左侧插入一个数;

(5) 在第k个插入的数右侧插入一个数

现在要对该链表进行M次操作,进行完所有操作后,从左到右输出整个链表。

注意:题目中第k个插入的数并不是指当前链表的第k个数。例如操作过程中一共插入了n个数,则按照插入的时间顺序,这n个数依次为:第1个插入的数,第2个插入的数,…第n个插入的数。

输入格式

第一行包含整数M,表示操作次数。

接下来M行,每行包含一个操作命令,操作命令可能为以下几种:

(1) “L x”,表示在链表的最左端插入数x。

(2) “R x”,表示在链表的最右端插入数x。

(3) “D k”,表示将第k个插入的数删除。

(4) “IL k x”,表示在第k个插入的数左侧插入一个数。

(5) “IR k x”,表示在第k个插入的数右侧插入一个数。

输出格式

共一行,将整个链表从左到右输出。

数据范围

1≤M≤100000
所有操作保证合法。

输入样例

10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2

输出样例

8 7 7 3 2 9

C++ 代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int N=100010;
//e[i]表示i号点的值
//l[i]表示i号点左边的点
//r[i]表示i号点右边的点
//idx表示用过的地址
int e[N],l[N],r[N],idx;
void init(){//初始化
    r[0]=1;//0号点是头结点
    l[1]=0;//1号点是尾结点
    idx=2;//地址0和1都用过了,所以目前地址是2
}
void Insert(int k,int x){//在k号点右边插入一个值为x的点
    e[idx]=x;//当前点的值是x
    r[idx]=r[k];//当前点的右边指向k号点的右边
    l[idx]=k;//当前点的左边指向k号点
    l[r[k]]=idx;//k号点右边的左边指向当前点
    r[k]=idx;//k号点右边指向当前点
    idx++;//地址用完+1
}
void Delete(int k){//删除k号点
    r[l[k]]=r[k];//k号点左边的右边变成k号点"原来"的右边
    l[r[k]]=l[k];//k号点右边的左边变成k号点"原来"的左边
}
int main(){
    int m;
    cin>>m;
    init();//一定不要忘记初始化
    while(m--){
        string op;//因为有两个字母的,所以用字符串存
        int k,x;
        cin>>op;
        if(op=="L"){
            cin>>x;
            Insert(0,x);//在头结点右边插入
        }
        else if(op=="R"){//在尾结点左边的右边插入
            cin>>x;
            Insert(l[1],x);
        }
        else if(op=="IL"){
            cin>>k>>x;
            Insert(l[k+1],x);//在k号点左边插入=在k号点左边的右边插入
        }
        else if(op=="IR"){
            cin>>k>>x;
            Insert(k+1,x);
        }
        else{
            cin>>k;
            Delete(k+1);
        }
    }
    for(int i=r[0];i!=1;i=r[i]) cout<<e[i]<<" ";//i=r[0],不能写成i=0,边界不在实质内容内
    return 0;
}



weixiao
1个月前

题目描述

实现一个单链表,链表初始为空,支持三种操作:

(1) 向链表头插入一个数;

(2) 删除第k个插入的数后面的数;

(3) 在第k个插入的数后插入一个数

现在要对该链表进行M次操作,进行完所有操作后,从头到尾输出整个链表。

注意:题目中第k个插入的数并不是指当前链表的第k个数。例如操作过程中一共插入了n个数,则按照插入的时间顺序,这n个数依次为:第1个插入的数,第2个插入的数,…第n个插入的数。

输入格式

第一行包含整数M,表示操作次数。

接下来M行,每行包含一个操作命令,操作命令可能为以下几种:

(1) “H x”,表示向链表头插入一个数x。

(2) “D k”,表示删除第k个输入的数后面的数(当k为0时,表示删除头结点)。

(3) “I k x”,表示在第k个输入的数后面插入一个数x(此操作中k均大于0)。

输出格式

共一行,将整个链表从头到尾输出。

数据范围

1≤M≤100000
所有操作保证合法。

输入样例

10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6

输出样例

6 4 6 5

C++ 代码

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int N=100010;
//head表示头结点指向的点,开始指向尾结点(-1)
//e[i]表示i号点的值
//ne[i]表示i号点指向的点的下标
//idx表示当前用到的地址
int head,e[N],ne[N],idx;
void init(){//初始化
    head=-1;//开始头结点指向尾结点(-1)
    idx=0;//还没用过地址,地址为0
}
void Head(int x){//在头结点后插入一个值为x的点
    e[idx]=x;//插入的点的值为x
    ne[idx]=head;//插入的点指向的点是"原来"头结点指向的点
    head=idx;//头结点指向当前点
    idx++;//地址用完+1
}
void Insert(int k,int x){//在下标是k的点后插入一个值为x的点
    e[idx]=x;//插入的点的值为x
    ne[idx]=ne[k];//插入的点指向k号点"原来"指向的点
    ne[k]=idx;//k号点指向当前点
    idx++;//地址用完+1
}
void Delete(int k){//删除k号点
    ne[k]=ne[ne[k]];//k号点指向"原来"指向的点指向的点
}
int main(){
    int m;
    cin>>m;
    init();//记住一定要先初始化,否则TLE
    while(m--){
        char op;
        cin>>op;

        if(op=='H'){
            int x;
            cin>>x;
            Head(x);
        }
        else if(op=='I'){
            int k,x;
            cin>>k>>x;
            Insert(k-1,x);
        }
        else{
            int k;
            cin>>k;
            if(!k) head=ne[head];
            Delete(k-1);
        }
    }
    for(int i=head;i!=-1;i=ne[i]) cout<<e[i]<<" ";
    return 0;
}


活动打卡代码 AcWing 667. 游戏时间

weixiao
5个月前
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int main(){
    int a,b;
    cin>>a>>b;
    if(a<b) cout<<"O JOGO DUROU "<<b-a<<" HORA(S)"<<endl;
    if(a==b) cout<<"O JOGO DUROU "<<24<<" HORA(S)"<<endl;
    if(a>b) cout<<"O JOGO DUROU "<<b-a+24<<" HORA(S)"<<endl;
    return 0;
}


活动打卡代码 AcWing 664. 三角形

weixiao
5个月前
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int main(){
    double a,b,c,d;
    cin>>a>>b>>c;
    if(a+b>c && a+c>b && b+c>a) printf("Perimetro = %.1f\n",a+b+c);
    else printf("Area = %.1f\n",(a+b)*c/2);
    return 0;
}


活动打卡代码 AcWing 659. 区间

weixiao
6个月前
#include<iostream>
using namespace std;
double n;
int main(){
    cin>>n;
    if(n<0 || n>100) puts("Fora de intervalo");
    if(n>=0.0 && n<=25.0) puts("Intervalo [0,25]");
    if(n>25.0 && n<=50.0) puts("Intervalo (25,50]");
    if(n>50.0 && n<=75.0) puts("Intervalo (50,75]");
    if(n>75.0 && n<=100.0) puts("Intervalo (75,100]");
    return 0;
}