[STL]hdu5233
来源:互联网 发布:黄品源 知乎 编辑:程序博客网 时间:2024/05/16 23:47
题意:
给出一组数据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 100005using 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/6882660int 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; } } }}
- [STL]hdu5233
- HDU5233
- hdu5233 Gunner II
- HDU5233 Gunner II && BestCoder Round #42
- HDU5233 Gunner II 离散化的各种方法
- stl
- stl
- STL
- STL
- STL
- STL
- STL
- STL
- STL
- stl
- STL
- STL
- STL
- JTable的清空小技巧以及JTable的详细介绍
- Swift运算符
- ASCII表
- C++类与对象(2) - class可以拥有自身类型的对象
- 结构
- [STL]hdu5233
- win10 10074版内存居高不下的解决办法
- Memcached客户端性能评测报告
- Quartz 2D基本介绍
- 异常处理语句
- win10 10074版本qq显示问题
- C++类与对象(3) - 空class&struct的大小
- C# 多线程并发编程资料汇总学习
- 职业选择