1、P8685 [蓝桥杯 2019 省 A] 外卖店优先级
“饱了么”外卖系统中维护着 N 家外卖店,编号 1N。每家外卖店都有一个优先级,初始时 (0(0 时刻)优先级都为 00。
每经过 11 个时间单位,如果外卖店没有订单,则优先级会减少 11,最低减到 00;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 22。
如果某家外卖店某时刻优先级大于 55,则会被系统加入优先缓存中;如果优先级小于等于 33,则会被清除出优先缓存。
给定 T 时刻以内的 M 条订单信息,请你计算 T 时刻时有多少外卖店在优先缓存中。
输入格式
第一行包含 3个整数 N 、 M 和 T。
以下 M 行每行包含两个整数 ts 和 id,表示ts 时刻编号 id 的外卖店收到。
一个订单。
输出格式
输出一个整数代表答案。
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int n,m,t;
int last[N],score[N];
struct node{
int time;
int id;
}d[N];
bool st[N];
bool cmp(node a,node b){
if(a.time !=b.time ) return a.time<b.time ;
return a.id <b.id ;
}
int main(){
cin>>n>>m>>t;
for(int i=0;i<m;i++)
cin>>d[i].time >>d[i].id ;
sort(d,d+m,cmp);
for(int i=0;i<m;){
int j=i;
while(j<m&&d[j].time==d[i].time&&d[j].id==d[i].id ) j++;
int nt=d[i].time ;
int nid=d[i].id ;
int count=j-i;
i=j;
score[nid]-=nt-last[nid]-1;
if(score[nid]<0) score[nid]=0;
if(score[nid]<=3) st[nid]=false;
score[nid]+=count*2;
if(score[nid]>5) st[nid]=true;
last[nid]=nt;
}
for(int i=1;i<=n;i++){
//检查最后有订单的时间
if(last[i]<t){
score[i]-=t-last[i];
if(score[i]<=3) st[i]=false;
}
}
int sum=0;
for(int i=1;i<=n;i++){
if(st[i]==true) sum++;
}
cout<<sum;
return 0;
}
2、P8686 [蓝桥杯 2019 省 A] 修改数组
题目描述
给定一个长度为 N 的数组 A=[A1,A2,⋯AN],数组中有可能有重复出现的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改 A2,A3,⋯,AN。
当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则小明会给 Ai 加上 1;如果新的 Ai 仍在之前出现过,小明会持续给Ai 加 11,直到 Ai 没有在 A1 ∼ Ai−1 中出现过。
当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。
现在给定初始的 A 数组,请你计算出最终的 A 数组。
输入格式
第一行包含一个整数 N。
第二行包含 N 个整数 1,2,⋯ ,A1,A2,⋯,AN。
输出格式
输出 N 个整数,依次是最终的 1,2,⋯ ,A1,A2,⋯,AN。
思路:可以使用并查集来写复习一下并查集的两个代码
//查找根节点的代码
int find(int x){
if(f[x]!=x) f[x]=find(f[x]);
return f[x];
}
//合并的代码
void join(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx!=fy) f[fx]=fy;
}
#include<iostream>
using namespace std;
const long long N=100009;
long long f[N];
long long find(int x){
if(f[x]!=x){
f[x]=find(f[x]);
}
return f[x];
}
void join(int a,int b){
int fx=find(a);
int fy=find(b);
if(fx!=fy){
f[fx]=fy;
}
}
int main(){
long long n,p;
scanf("%lld",&n);
for(long long i=1;i<100009;i++)
f[i]=i;
for(long long i=1;i<=n;i++){
scanf("%lld",&p);
p=find(p);
printf("%lld ",p);
join(p,p+1);
}
return 0;
}
3、P8716 [蓝桥杯 2020 省 AB2] 回文日期
找到日期符合回文日期,第二个日期符合ABABBABA
思路:从给出的日期向后找即可,找到第一个就可以,用found做标记
//关于处理日期的几个注意点
const int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31}
int runnian(int y){
if(y%4==0&&y%100!=0||y%400==0) return 1;
return 0;
}
int getday(int y,int m){
if(m==2) return 28+runnian(y);
return month[m];
}
void nextday(int& y,int& m,int& d){
d++;
if(d>getday(y,m){
d=1;
m++;
if(m>12){
m=1;
y++;
}
}
}
//快速输入年月日的表示方式
scanf("%04d%02d%02d",&y,&m,&d);
//还有一个特殊的函数sprintf,可以快速赋值给字符串
char s[10]={0};
sprintf(s,"%04d%02d%02d",y,m,d);
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int y,m,d;
const int months[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int run(int y){
if(y%4==0&&y%100!=0||y%400==0)
return 1;
return 0;
}
int getday(int y,int m){
if(m==2) return 28+run(y);
return months[m];
}
void nextday(int& y,int& m,int& d){
d++;
if(d>getday(y,m)){
d=1;
m++;
if(m>12){
m=1;
y++;
}
}
}
bool check1(char s[]){
//检查是不是回文日期的
for(int i=0,j=7;i<j;i++,j--){
if(s[i]!=s[j]) return false;
}
return true;
}
bool check2(char s[]){
//检查是不是ABABBABA
char a=s[0],b=s[1],c=s[2],d=s[3];
if(a==c&&b==d&&a!=b) return true;
return false;
}
int main(){
scanf("%04d%02d%02d",&y,&m,&d);
char s[10]={0};
bool found1=false,found2=false;
while(!found1||!found2){
nextday(y,m,d);
sprintf(s,"%04d%02d%02d",y,m,d);
if(check1(s)){
if(!found1){
puts(s);
found1=true;
}
if(!found2&&check2(s)){
puts(s);
found2=true;
}
}
}
return 0;
}