7月10日小学期学习记录

修改数组
题目描述

给定一个长度为 𝑁 的数组𝐴=[𝐴1,𝐴2,⋅⋅⋅,𝐴𝑁],数组中有可能有重复出现的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改𝐴2,𝐴3,⋅⋅⋅,𝐴𝑁
当修改 𝐴𝑖 时,小明会检查 𝐴𝑖 是否在 𝐴1 ∼ 𝐴𝑖−1 中出现过。如果出现过,则小明会给 𝐴𝑖 加上 1 ;如果新的 𝐴𝑖 仍在之前出现过,小明会持续给 𝐴𝑖 加 1 ,直 到 𝐴𝑖 没有在 𝐴1 ∼ 𝐴𝑖−1 中出现过。
当𝐴𝑁 也经过上述修改之后,显然 𝐴 数组中就没有重复的整数了。
现在给定初始的 𝐴 数组,请你计算出最终的 𝐴 数组。

输入描述

第一行包含一个整数 𝑁。
第二行包含 𝑁 个整数𝐴1,𝐴2,⋅⋅⋅,𝐴𝑁 。
其中,1≤𝑁≤105,1≤𝐴𝑖≤106 。

输出描述

输出 𝑁 个整数,依次是最终的 𝐴1,𝐴2,⋅⋅⋅,𝐴𝑁。

输入输出样例

示例
输入

5
2 1 1 3 4
输出
2 1 3 4 5

运行限制
最大运行时间:1s
最大运行内存: 256M

题解

难度不大哈
最初想到的肯定是暴力嘛,蓝桥杯有部分分,试了下,90分。(不行你送我10分呢?)分数相当可观,代码如下

#include<bits/stdc++.h>
using namespace std;

int n,a[100005];
bool flag[1000005];
int main(){
    int i,j,k;
    cin>>n;
    for(i=1;i<=n;i++){
        cin>>a[i];
        if(!flag[a[i]]){
            flag[a[i]]=1;
        }
        else {
            while(flag[a[i]]==1)a[i]++;
        }
        flag[a[i]]=1;
        printf("%d ",a[i]);
    }
    return 0;
}

然后嘛,你观察,a[i]没有半点用处,你就不需要算了,然后你看看啊,时间消耗在一个一个找的上面,那我们记录每个数的个数不就行了,每次加当前数的个数,速度也加快了,满分代码。代码如下

#include<bits/stdc++.h>
using namespace std;

int n,x,cnt[1000010];  //cnt[x]表示当前整数x出现的次数
int main(){
  int i,j,k;
  scanf("%d",&n);
  for(i=1;i<=n;i++){
    scanf("%d",&x);
    while(cnt[x]){
      cnt[x]++;
      x+=cnt[x]-1;
    }
    cnt[x]++;
    printf("%d ",x);
  }
  return 0;
}
外卖店优先级
题目描述

"饱了么"外卖系统中维护着 𝑁 家外卖店,编号 1 ∼ 𝑁。每家外卖店都有 一个优先级,初始时 (0 时刻) 优先级都为 0。
每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减 到 0;而如果外卖店有订单,则优先级不减反加,每有一单优先级加 2。
如果某家外卖店某时刻优先级大于 5,则会被系统加入优先缓存中;如果 优先级小于等于 3,则会被清除出优先缓存。
给定 𝑇 时刻以内的 𝑀 条订单信息,请你计算 𝑇 时刻时有多少外卖店在优 先缓存中?

输入描述

第一行包含 3 个整数 𝑁,𝑀,𝑇。
以下𝑀 行每行包含两个整数 𝑡𝑠,𝑖𝑑,表示 𝑡𝑠 时刻编号 𝑖𝑑 的外卖店收到一个订单。
其中,1≤𝑁,𝑀,𝑇≤105,1≤𝑡𝑠≤𝑇,1≤𝑖𝑑≤𝑁

输出描述

输出一个整数代表答案。

输入输出样例

示例
输入

2 6 6
1 1
5 2
3 1
6 2
2 1
6 2

输出

1

样例解释:

6 时刻时,1 号店优先级降到 3,被移除出优先缓存;2 号店优先级升到 6, 加入优先缓存。所以是有 1 家店 (2 号) 在优先缓存中。

运行限制

最大运行时间:2s
最大运行内存: 256M

题解

模拟题,按照要求模拟就行了
下面这段题解来自老师,用了数据结构的map操作以及并查集的思想,相当巧妙
1,模拟题,使用C++做的,为了使用map模拟桶结构,如果使用二维数组模拟桶,空间复杂度太高。所以,就算使用C写,也得写个链表,然后使用链表数组模拟桶。
2,map<int,map<int,int> > v;
这个v就是桶。是下面这个的一个结构
时间点
1 5 77 88 99 xxx ………………………………
外卖店
1 x x x x x x ………………………………
2 x x x x x x ………………………………
……
……
n x x x x x x ………………………………
即v[i][j]里面存放的x,表示在j时刻,外卖店i收到的订单数量。
3,vector flag(n+1);标记数组,flag(i)标记外面店i是否在缓冲之中。
4, 根据题意读数据,利用map自动给外卖店和时间点排序
while(m–)
{
int ts,id;
cin>>ts>>id;
v[id][ts]++;
}
5,map<int,map<int,int> >::iterator r=v.begin();
for(;r!=v.end();++r)
{map<int,int>& tmp=r->second;
map<int,int>::iterator r1=tmp.begin();
int time=0,pro=0;

}
外层循环,遍历每个外卖店.局部变量time表示前一个时间点,pro表示前一个时间点,外卖店r->first的优先级。
6,
for(;r1!=tmp.end();++r1)
{
pro-=r1->first-1-time;
if(pro<0) pro=0;
if(pro<=3&&flag[r->first])flag[r->first]=0;
pro+=2*r1->second;
if(pro>5&&!flag[r->first])flag[r->first]=1;
time=r1->first;
}
内层循环,遍历当前外卖店的,每个增加订单的时间点。前3句,处理的是当前时刻(r1->first) 的前一刻(r1->first-1),外卖店r->first的优先级和是否位于缓冲区。后三句,处理的是当前时刻(r1->first) ,外卖店
r->first的优先级和是否位于缓冲区。

7, pro-=t-time;
if(pro<=3&&flag[r->first])flag[r->first]=0;
if(flag[r->first]) count++;
外层循环的后3句,相当于处理终止时刻t,外卖店r->first的优先级和是否位于缓冲区。

#include <map>
#include <vector>
 
#include <iostream>
using namespace std;
int main()
{   
    int n,m,t,count=0;
    cin>>n>>m>>t;
    map<int,map<int,int> >  v;
    vector<bool> flag(n+1);
    while(m--)
    {
    	int ts,id;
    	cin>>ts>>id;
    	v[id][ts]++;
	}
	map<int,map<int,int> >::iterator r=v.begin();
	for(;r!=v.end();++r)
	{
		map<int,int>& tmp=r->second;
		map<int,int>::iterator r1=tmp.begin();
		int time=0,pro=0;
		for(;r1!=tmp.end();++r1)
		{
			pro-=r1->first-1-time;
			if(pro<0) pro=0;
			if(pro<=3&&flag[r->first])flag[r->first]=0;
			pro+=2*r1->second;
			if(pro>5&&!flag[r->first])flag[r->first]=1;
			time=r1->first;
		}
		pro-=t-time;
		if(pro<=3&&flag[r->first])flag[r->first]=0;
		if(flag[r->first]) count++;
	}
	cout<<count;
	return 0;
}

下面提供暴力…所以你不会就暴力吧…

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <utility>
#define x first 
#define y second

using namespace std;

typedef pair<int,int> PII;

const int N=1e5+10;

int n,m,T,res;
int last[N],score[N];
PII order[N];
bool st[N];

int main(){

  scanf("%d%d%d",&n,&m,&T);//输入

  for(int i=0;i<m;i++)scanf("%d%d",&order[i].x,&order[i].y);//输入

  sort(order,order+m);

  for(int i=0;i<m;i++){

    int t=order[i].x, id=order[i].y;
    score[id]-=t-last[id]-1;
    if(score[id]<0)score[id]=0;
    if(score[id]<=3)st[id]=false;

    int j=i;
    
    while(j<m && order[i]==order[j])j++;
    int cnt=j-i;
    i=j-1;
    score[id]+=cnt*2;
    if(score[id]>5)st[id]=true;
    last[id]=t;
  }
  for(int i=1;i<=n;i++){
    if(last[i]<T){
      score[i]-=T-last[i];
      if(st[i] && score[i]<=3)st[i]=false;
    }
  }
  for(int i=1;i<=n;i++){
    res+=st[i];
  }
  cout<<res;

  return 0;
}
  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

徐苏洋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值