[STL]hdu5233

题意:

给出一组数据n个数,m个询问q,问最近的q的输入下标是多少?

分析:

首先数据量比较大100000,查询的话肯定要用些技巧,刚开始想的是二分查询,用set,可是不知道set里放数据结构struct如何按照关键字lower_bound()。后来看了官方题解,先把数据离散话,然后利用set[]来存储下标。那么输出的时候就直接输出begin,删除也可以erase().

这里有个trick,刚开始用的vector q[],然后T。。。后来换set就A了,原来vector<>的push_back()是O(n)的,set的inset是O(logn).

这里简单查一下vector push_back的知识,当每次push_back的时候vector法先空间不够的时候就会copy元素,然后扩大空间,vector 的 push_back 在发现空间不足时自动将空间以 2 的指数增长:0 -> 1 -> 2 -> 4 -> 8 -> 16 -> 32 …

引用:

http://blog.csdn.net/tyzhaoqi2004/article/details/6882660

vector管理内存的方式是内存不够用时,就分配capacity大小的内存,每次重新分配内存,都要copy之前放入的元素,capacity为已经分配的内存。

例如:push_back n个int元素,n为2的幂次加1

元素序号 copy元素 capacity

1 1 1

2 2 2

3 3 4

4 1 4

5 5 8

.。。。

n n 2n

归纳得到copy元素次数字和为

1+2+4+8.。。+(n-1)/2+(n-1)+n

前面部分为一个等比数列,求和为(n-1)/2,最后数列求和为3n-1/3,时间复杂度为O(n)。

所以在不指定reverse的时候,vector push_back n个元素的时间复杂度为O(n)。

对于set:

set::find和set::insert消耗时间级别都为logN.



可是试了一下预先分配vector的空间大小,还是T。。。

好吧,来看一下vector的erase函数

    template<typename _Tp,_Alloc>typename vector<_Tp,_Alloc>::iterator
    vector<_Tp,_Alloc>::erase(iterator __postion) {
        if (__postion + 1 != end())
            std::copy(__postion + 1, end(), __postion);
        --this->_M_impl._M_finish;
        this->_M_impl.destroy(this->_M_impl._M_finish);
        return __postion;
    }  

它是O(n)是把删除数据后面的数据copy到前面。copy是把删除元素位置后面元素向前移位, 然后 –finish把end位向前移动, 这2句都好理解保持内存连续把删除的空位补上同时把队尾往前挪。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#define read freopen("q.in","r",stdin)
#define LL long long
#define maxn 100005
using namespace std;
set<int>  mp[maxn];
map<int,int> c;
//http://www.2cto.com/kf/201108/100912.html
//http://blog.csdn.net/tyzhaoqi2004/article/details/6882660
int main()
{
    //read;
   int n,m;
   while(scanf("%d%d",&n,&m)!=EOF)
   {
       int i,j,q,x,t=0;
       for(i=1;i<=n;i++)
        mp[i].clear();
        c.clear();
       for(i=0;i<n;i++)
       {
          scanf("%d",&x);
          if(!c[x])c[x]=++t;
          mp[c[x]].insert(i+1);

         // cout<<c[x]<<" ";
       }
       //for(i=1;i<=t;i++)cout<<c[i]<<" ";
    //   cout<<endl;
       for(i=0;i<m;i++)
       {
          scanf("%d",&q);
          if(mp[c[q]].size()==0)
          {
             printf("-1\n");
          }
          else
          {
            //  cout<<mp[q].size()<<" %% "<<endl;
             printf("%d\n",*(mp[c[q]].begin()));
             mp[c[q]].erase(mp[c[q]].begin());
            // cout<<mp[q].size()<<" %% "<<endl;
          }
       }

    }
}
时间: 2024-10-08 10:14:28

[STL]hdu5233的相关文章

HDU5233 Gunner II 离散化的各种方法

题目链接: HDU5233 题意: n棵树依次排好,每棵树都有一个高度,树的顶端有一只鸟. 猎人会打M枪,每一枪都能从高度为X的树上打下一只鸟,问每一枪打下的鸟是从  编号多少的树 上掉下来的 题解思路: 因为树的高度能达到(10^9)  而树的数量最多10^5  所以离散化   将所有高度为X的树离散化为 高度为第X高的树 有多种方法. 1  stl去重+set版: #include<iostream> #include<cstdio> #include<cstring&g

STL学习思想

1.模版:一定要注意参数和返回值的模版 2.STL一系列的API:一定要注意返回值 3.容器中的都是值拷贝,而不是引用,在执行插入时,内部实行拷贝动作,所以STL中插入类时,一般都必须:无参构造函数,拷贝构造函数,重载=运算符,必须的自己重写,达到深拷贝!!! 4.一元谓词:函数只有一个参数,谓词:代表函数的返回值必须为bool类型;   二元谓词:函数只有二个参数,谓词:代表函数的返回值必须为bool类型; 5.算法和具体的数据类型相分离:通过函数对象(仿函数)来实现,本质:函数指针!!! 6

C++ STL学习——vector

学过C++的人肯定会很熟悉STL标准模板库,STL其实就是封装了一系列的接口,供我们调用.很多函数或者算法的实现不需要我们从头开始写,大大提高我们的编程效率.这篇博客在简单介绍STL的情况下,会详细的来介绍vector的使用. STL共有六大组件: 一.容器(Container):是一种数据结构,如list,vector,deque,queue等,以模板类的方法提供,为了访问容器中的数据,可以使用由容器类提供的迭代器. 二.迭代器(Iterator):提供了访问容器中对象的方法. 三.算法(Al

C++ STL中Map的按Key排序和按Value排序

原文  http://blog.csdn.net/iicy266/article/details/11906189 map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择. 我们这样定义,map<string, int>,其中学生姓名用string类型,作为Key:该学生的成绩用int类型,作为value.这样一来,我们可以根据学

stl容器区别: vector list deque set map及底层实现

在STL中基本容器有: vector.list.deque.set.map set 和map都是无序的保存元素,只能通过它提供的接口对里面的元素进行访问 set :集合, 用来判断某一个元素是不是在一个组里面,使用的比较少 map :映射,相当于字典 ,把一个值映射成另一个值,如果想创建字典的话使用它好了 底层采用的是树型结构,多数使用平衡二叉树实现 ,查找某一值是常数时间,遍历起来效果也不错, 只是每次插入值的时候,会重新构成底层的平衡二叉树,效率有一定影响. vector.list.dequ

STL vector,deque,list

一.vector可变长的动态数组必须包含头文件 #include <vector>支持随机访问迭代器• 根据下标随机访问某个元素时间为常数• 在尾部添加速度很快• 在中间插入慢所有STL算法 都能对vector操作 构造函数初始化:vector();无参构造函数, 将容器初始化成空的vector(int n);将容器初始化成有n个元素vector(int n, const T & val);假定元素类型是T, 将容器初始化成有n个元素, 每个元素的值都是valvector(iterat

C++ STL hash_map的使用以及STL hash_map的大“坑”

计算机编程中经常会用到hash表,而在C++中,使用STL编程更是少不了的.本文将介绍STL中hash_map的使用.在hash_map中使用自定义类型作为key值的方法以及在使用char *类型作为key值时遇到的问题. 一.需要的头文件以及命名空间 在linux下使用STL hash_map除了需要引用其所在头文件<hash_map>之外还要引用其命名空间.像这样写  1 using namespace __gnu_cxx; 二.hash_map的定义 先来看看hash_map是怎么定义的

c++ STL容器初探

什么是容器 首先,我们必须理解一下什么是容器,在C++ 中容器被定义为:在数据存储上,有一种对象类型,它可以持有其它对象或指向其它对像的指针,这种对象类型就叫做容器.很简单,容器就是保存其它对象的对象,当然这是一个朴素的理解,这种"对象"还包含了一系列处理"其它对象"的方法,因为这些方法在程序的设计上会经常被用到,所以容器也体现了一个好处,就是"容器类是一种对特定代码重用问题的良好的解决方案". 容器还有另一个特点是容器可以自行扩展.在解决问题时

stl源码剖析 详细学习笔记 算法总览

//****************************基本算法***************************** /* stl算法总览,不在stl标准规格的sgi专属算法,都以 *加以标记 算法名称              算法用途         质变                   所在文件 accumulate          元素累计            否                   <stl_numeric.h> adjacent_differenc