这是一个令人开(吐)心(血)的故事
今天早上,我本来开开心心的在日常摸鱼。
突然“一代赌王”(外号之一)妹子发来了一道算法题
我见过它,新建文档,很普通的一道蓝桥算法题嘛,虽然咱技术很渣,但跟妹子做一道基础水题应该还是没什么难度的
…
…
…
…
…吧
打开这个算法所在的竞赛,位置很靠前,
嗯
感觉更有信心了.....呢(变音)?
这个提交通过率好像有点不对啊
解析题目,哎呀,不就是队列记录新建与文件状态吗,遍历维护一个数组就行了
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
int[] arr = new int[100000];
int n = scanner.nextInt();
for(int i=0;i<n;i++){
String string = scanner.next();
if(string.charAt(0)=='N'){//New
for(int j=0;j<n;j++){
if(arr[j]==0){
arr[j]=1;
System.out.println(j+1);
break;
}
}
}else{//Delete
int a = scanner.nextInt();
if(arr[a-1]==1){
arr[a-1]=0;
System.out.println("Successful");
}else if(arr[a-1]==0){
System.out.println("Failed");
}
}
}
}
}
欧了!结束战斗
超时???,什么鬼?
package main
import "fmt"
func SortSlice(slice []int) {
for i := 0; i < len(slice)-1; i++ {
//遍历i位以后的所有元素,如果比i位元素小,就和i位元素互换位置
for j:=i+1;j<len(slice) ;j++ {
if slice[j] < slice[i]{
slice[i],slice[j] = slice[j],slice[i]
}
}
}
}
func main() {
var a [100001]int
var str string
aa := make([]int, 0, 100)
n,t:=0,0
j:=1
for {
c,_ :=fmt.Scan(&n)
if c==0{
break
}else{
for i:=1;i<=n;i++{
fmt.Scan(&str)
if str=="New"{
if len(aa)>0{
le :=len(aa)
if le == 1 {
a[aa[0]]=1
fmt.Println(aa[0])
aa=[]int{}
}else {
SortSlice(aa)
a[aa[0]]=1
fmt.Println(aa[0])
aa = append(aa[:0], aa[1:]...)
}
}else {
a[j]=1
fmt.Println(j)
j++
}
}else {
fmt.Scan(&t)
if a[t]==1{
a[t]=0
aa = append(aa,t)
fmt.Println("Successful")
}else {
fmt.Println("Failed")
}
}
}
break
}
}
}
然后…
这什么鬼??,在次审视这个题
然后我发现
淦!
它比蓝桥杯的水题增加了100倍,100000次操作
这玩意一搞,顿时心态全无,怪不得通过率这么诡异。
看了看其他小伙伴的代码什么c,python,C++写的都不。。。嗯???C++???
为什么它怎么优秀?
仔细看了一下代码
priority_queue<int> que;
const int SIZE = 1e6 + 7;
bool Vis[SIZE]; int cnt;
好家伙
优先队列!!
原来是你小子
通过优先队列对存储的删除下标排序,在新建时首先对队列pop,既可以实现要求,又能完美免去一层遍历。
妙啊!!
but,
我们的妹子用的是GO
而咱GO是没有对象的!!!
啊,
不是,
是没有优先队列的。
所以麻烦的来了,我还得自己先实现一个
一般情况下讲,我可以使用priority queue实现优先级队列
但是我这个网络吧
大锅这话非常贴切
而且,Y(ya,一声,一种语气词)导包,牛客上也运行不了啊
所以莫得办法,只能依靠Heap来实现一个了
package main
import (
"container/heap"
"fmt"
"strconv"
)
// QItem 表示存储到这个队列中需要实现的接口
type QItem interface {
//QItem接口要实现的方法,要求接收的变量是QItem类型,返回值为bool
Less(item QItem) bool
}
/*
priorityQueueImpl 用于优先队列底层实现,
优先队列涉及两部分,数据排序与数据压入弹出pop和push,也就是Heap包中的几个方法,
Heap基于接口实现,所以我们可以通过实现两个接口的基础方法去嵌套继承两个方法
声明一个[]QItem类型的类型别名为priorityQueueImpl
这里我们的priorityQueueImpl实际上就是实现了heap
*/
type priorityQueueImpl []QItem
// 下面实际上是实现了一个[]QItem类型的的Head方法
// Len 获取队列长度,为priorityQueueImpl类型实现len方法,返回值为int
func (pqi priorityQueueImpl) Len() int {
return len(pqi)
}
/*
Less方法 用来进行元素比较
为priorityQueueImpl类型实现less方法,实现QItem接口
priorityQueueImpl类型本质上还是数组,传入的i,j作为下标
返回的是比对结果的布尔值
因为我们实现了Less,Swap,Len这三个方法,
因此priorityQueueImpl就实现了Interface接口
*/
func (pqi priorityQueueImpl) Less(i, j int) bool {
/*
这里左侧点进去可以见到sort
这里的less是拿的实现该方法的priorityQueueImpl实例的less方法
*/
return pqi[i].Less(pqi[j])
}
// Swap 进行交换
func (pqi priorityQueueImpl) Swap(i, j int) {
//交换方法
pqi[i], pqi[j] = pqi[j], pqi[i]
}
// Push 用来将一个对象压入队列中
func (pqi *priorityQueueImpl) Push(x interface{}) {
item := x.(QItem)
*pqi = append(*pqi, item)
}
// Pop 将一个对象弹出队列
func (pqi *priorityQueueImpl) Pop() interface{} {
old := *pqi
n := len(old)
item := old[n-1]
*pqi = old[0 : n-1]
return item
}
/*
PriorityQueue 实现优先队列
PriorityQueue继承了上面的priorityQueueImpl实现的方法
*/
type PriorityQueue struct {
priorityQueueImpl
}
// NewPriorityQueue 用来构建PriorityQueue
func NewPriorityQueue() *PriorityQueue {
var pq PriorityQueue
//pq是我们定义的PriorityQueue的变量,它内部是一个实现了head方法的[]QItem
//然后我们使用heap的init方法初始化这个[]QItem,并返回
heap.Init(&pq.priorityQueueImpl)
return &pq
}
//下面是给这个PriorityQueue实现一些方法
// Push 用来将一个对象压入到队列中,函数接受实现了接口的对象
func (pq *PriorityQueue) Push(item QItem) {
heap.Push(&pq.priorityQueueImpl, item)
}
// Pop 用来从队列中弹出一个对象
func (pq *PriorityQueue) Pop() QItem {
return heap.Pop(&pq.priorityQueueImpl).(QItem)
}
// Front 用来获取当前队列中的最小值
func (pq *PriorityQueue) Front() QItem {
// 队列中第一位应该就是最小值
return pq.priorityQueueImpl[0]
}
// Length 用来获取当前队列的长度
func (pq *PriorityQueue) Length() int {
return pq.priorityQueueImpl.Len()
}
//如果希望一个结构可以存储到PriorityQueue中,需要实现QItem接口中的函数,即Less函数。
type Int int
//这里是示例使用,自定义int来实现less方法,也就是实现了QItem接口
//Int实现了less也就可以创建Int实例对象,然后就可以用NewPriorityQueue来处理这个类型的实例
func (i Int) Less(j QItem) bool {
return i < j.(Int)
}
func main() {
var a [100001]int
var str string
pq := NewPriorityQueue()
n,t:=0,0
j:=1
for {
c,_ :=fmt.Scan(&n)
if c==0{
break
}else{
for i:=1;i<=n;i++{
fmt.Scan(&str)
le :=pq.Len()
if str=="New"{
if le==0{//如果队列为空
a[j]=1
fmt.Println(j)
j++
}else{//将队列中的首位取出
it :=pq.Pop()
/*因为我们做实例使用的是Int,而取出的是一个QItem对象,
数据队列使用的是int,所以要进行一下处理,先将之转换为字符串,
然后将字符串转换为int,因为下标都是整数,这样做并不会出现什么问题*/
str1 :=fmt.Sprintf("%d",it)
intl, err := strconv.Atoi(str1)
if err != nil {
fmt.Println("有问题")
}
a[intl]=1
fmt.Println(intl)
}
}else{
fmt.Scan(&t)
if t<=len(a)&&a[t]==1{
a[t]=0
//我们存入的需要是实现了QItem的对象
pq.Push(Int(t))
fmt.Println("Successful")
}else {
fmt.Println("Failed")
}
}
}
break
}
}
}
众所周知,牛客算法对于空间复杂度采用了和sc玩家碰见对手非理性操作时的常用招式----“不管!”
因此我并没有考虑其他,甭管什么样子,什么优化,在时间内先做对再讲!
终于
在一身悦耳的特效声音后
我成功的通过了
虽然对比C++多用了很多空间
然鹅
这个时候
已经错过了干饭人的最佳干饭时间
而在我兴致勃勃想要去和妹子讲解时,却发现她早早的就放弃了这道题
还来了句
好麻烦啊
麻烦啊
烦啊
啊
啊!!!