链接:https://ac.nowcoder.com/acm/contest/4462/A
来源:牛客网
A-操作序列
时间限制:C/C++ 5秒,其他语言10秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
给出一个长度无限的数列,初始全部为零,有三种操作:
- 增加操作:给下标为 ttt 的数加 ccc 。特别注意,如果在下标 [t−30,t+30][t-30,t+30][t−30,t+30] 内有不为零的数,增加操作无效。
- 削减操作:让数列中下标最小的不为零数变为零。
- 查询操作:查询数列中下标为 ttt 的数字是多少。
输入描述:
第一行包含一个整数 N,1≤N≤106N,1 \le N \le 10^6N,1≤N≤106,表示操作总数。
随后 N 行,每行由两个数字或一个数字组成。
若一行中有两个数字,分别代表增加操作的 t,c 。
若一行中只有数字-1,执行削减操作。
若一行中只有一个不为 -1的数字,则代表查询操作的数字 t。
保证t,c均为非负整数且在整形范围内。
输出描述:
削减操作时,先输出该数字,再变为零
若序列元素全为零,则削减操作无效,此时输出 "skipped"
查询时,输出该位置上的数
示例1
输入
7 140 1 120 2 100 3 120 100 -1 100
输出
0 3 3 0
示例2
输入
4 140 3 -1 140 1 -1
输出
3 1
示例3
输入
3 -1 -1 -1
输出
skipped skipped skipped
第一次用set写题,边百度用法边写,set具有对键值自动从小打大排序的功能;所以可以再set里面放pair来存放下标和对应的值;
给出代码先阐述一下set的操作(大佬请自动忽略qaq)
这里用到set的两个重要用法:
set.lower_bound(x) 返回第一个大于等于y(y是括号里所给数据类型x的键值)的元素的迭代器;注意是迭代器(也就是地址)
set.upper_bound() 返回第一个大于y(y是括号里所给数据类型x的键值)的元素的迭代器;注意是迭代器(也就是地址)
两者的具体解释和原理详见这篇文章:关于lower_bound( )和upper_bound( )的常见用法
AC代码:
(还有个细节之处值得本弱鸡记住的是,cin输入会自动忽略空格,scanf可以读入空格和换行符,所以平时还是多用scanf吧)
#include <bits/stdc++.h>
using namespace std;
set<pair<int,int> > st;
int main()
{
int n;
cin >>n;
while(n--)
{
int t,c,flag=0;
char ss;
cin >>t;
scanf("%c",&ss);
if(ss==' ')
{
flag=1;
cin >>c;
}
if(flag)
{
if(!st.size()) st.insert(make_pair(t,c));
else
{
int ff=1;
auto top=st.lower_bound(make_pair(t,0));
if(top==st.begin())
{
if(abs(st.begin()->first-t)<=30) ff=0;
}
else
{
auto res=top--;
if(abs(res->first-t)<=30||abs(top->first-t)<=30) ff=0;
}
if(ff) st.insert(make_pair(t,c));
}
}
else if(t==-1)
{
if(st.size()) cout <<st.begin()->second<<endl,st.erase(st.begin());
else puts("skipped");
}
else
{
auto top=st.lower_bound(make_pair(t,0));
if(top->first==t) cout <<top->second<<endl;
else cout <<0<<endl;
}
}
}