这道题给人的感觉就是恶心人。
刚开始完全不懂怎么找含有x的区间,后来看别人都说用vector,然后用之,发现很好用啊,支持插入和擦除操作,我原来竟然不知道还有这些功能.
vector中的insert函数
iterator insert( iterator loc, const TYPE &val );
void insert( iterator loc, size_type num, const TYPE &val );
void insert( iterator loc, input_iterator start, input_iterator end );
insert() 函数有以下三种用法:
在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器,
在指定位置loc前插入num个值为val的元素
在指定位置loc前插入区间[start, end)的所有元素 .
这道题用到了第一个函数
然后还有erase函数
vector::erase():从指定容器删除指定位置的元素或某段范围内的元素
vector::erase()方法有两种重载形式
如下:
iterator erase( iterator _Where);
1.iterator erase( iterator _First, iterator _Last);
如果是删除指定位置的元素时:
返回值是一个迭代器,指向删除元素下一个元素;如果是删除某范围内的元素时:返回值也表示一个迭代器,指向最后一个删除元素的下一个元素;
转载之: 来自http://blog.sina.com.cn/s/blog_6377b8e60100ino6.html
MSDN上的例子
// vector_erase.cpp
// compile with: /EHsc
#include <vector>
#include <iostream>
int main( )
{
using namespace std;
vector <int> v1;
vector <int>::iterator Iter;
v1.push_back( 10 );
v1.push_back( 20 );
v1.push_back( 30 );
v1.push_back( 40 );
v1.push_back( 50 );
cout << "v1 =" ;
for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
cout << " " << *Iter;
cout << endl;
v1.erase( v1.begin( ) );
cout << "v1 =";
for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
cout << " " << *Iter;
cout << endl;
v1.erase( v1.begin( ) + 1, v1.begin( ) + 3 );
cout << "v1 =";
for ( Iter = v1.begin( ) ; Iter != v1.end( ) ; Iter++ )
cout << " " << *Iter;
cout << endl;
}
Output
v1 = 10 20 30 40 50
v1 = 20 30 40 50
v1 = 20 50
大家可以知道,需删除元素10只要指定该元素对应的迭代器传给erase就OK了;
那现在如果该容器中有两个元素10要怎么删除呢?
接着我做下修改,向容器中添加一新的元素10
v1.push_back( 10 );
大多数初学者在不熟知erase的原理的时候,也会像我一样这样处理,
一一遍历容器找到元素值为10,然后一一删除
for(Iter = v1.begin(); Iter != v1.end(); Iter++)
{
if(*Iter == 10)
{
v1.erase(Iter);
}
}
当试着重新build程序后运行,会出现包含有如下信息的错误
_Myptr < ((_Myvec *)(this->_Mycont))->_Mylast
其他出现这种原因是没搞懂erase的原理,当调用erase()后Iter迭代器就失效了,变成了一野指针。
所以要处理这种问题,关键是要解决调用erase()方法后,Iter迭代器变成野指针的问题,
这个时候呢给他赋一个新的迭代器给他。
for(Iter = v1.begin(); Iter != v1.end(); Iter++)
{
if(*Iter == 10)
{
v1.erase(Iter);
Iter = v1.begin(); //当erase后,旧的容器会被重新整理成一个新的容器
}
}
重新Iter迭代器指定下一个元素.
上面那种方法是给Iter重新赋于新v1的begin迭代器。
还有一种方法是直接赋删除元素的下一个迭代器给Iter
实现方法的代码如下:
for(Iter = v1.begin(); Iter != v1.end(); Iter++)
{
if(*Iter == 10)
{
Iter = v1.erase(Iter);//Iter为删除元素的下一个元素的迭代器
//即第一次这段语句后Iter 会是20,大家可以通过debug调试出来查看下数值
}
if(Iter == v1.end()) //要控制迭代器不能超过整个容器
{
break;
}
}
/*
ID: sdj22251
PROG: subset
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 50005
#define eps 1e-11
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
struct node
{
int left, right, mid;
int lmx, rmx, mx, cover;
}tree[4 * MAXN];
void up(int C)
{
tree[C].lmx = tree[L(C)].lmx;
tree[C].rmx = tree[R(C)].rmx;
if(tree[L(C)].lmx == tree[L(C)].right - tree[L(C)].left + 1) tree[C].lmx += tree[R(C)].lmx;
if(tree[R(C)].rmx == tree[R(C)].right - tree[R(C)].left + 1) tree[C].rmx += tree[L(C)].rmx;
tree[C].mx = max(tree[L(C)].rmx + tree[R(C)].lmx, max(tree[L(C)].mx, tree[R(C)].mx));
}
void down(int C)
{
if(tree[C].cover != -1)
{
tree[L(C)].cover = tree[R(C)].cover = tree[C].cover;
tree[L(C)].lmx = tree[L(C)].rmx = tree[L(C)].mx = tree[C].cover ? 0 : tree[L(C)].right - tree[L(C)].left + 1;
tree[R(C)].lmx = tree[R(C)].rmx = tree[R(C)].mx = tree[C].cover ? 0 : tree[R(C)].right - tree[R(C)].left + 1;
tree[C].cover = -1;
}
}
void make_tree(int s, int e, int C)
{
tree[C].left = s;
tree[C].right = e;
tree[C].mid = (s + e) >> 1;
tree[C].cover = 0;
tree[C].lmx = tree[C].rmx = tree[C].mx = e - s + 1;
if(s == e) return;
make_tree(s, tree[C].mid, L(C));
make_tree(tree[C].mid + 1, e, R(C));
}
void update(int s, int e, int v, int C)
{
if(tree[C].left >= s && tree[C].right <= e)
{
tree[C].cover = v;
tree[C].lmx = tree[C].rmx = tree[C].mx = v ? 0 : tree[C].right - tree[C].left + 1;
return;
}
down(C);
if(tree[C].mid >= s) update(s, e, v, L(C));
if(tree[C].mid < e) update(s, e, v, R(C));
up(C);
}
int query(int p, int C)
{
if(tree[C].left == tree[C].right) return tree[C].left;
down(C);
if(tree[L(C)].mx >= p) return query(p, L(C));
else if(tree[L(C)].rmx + tree[R(C)].lmx >= p) return tree[C].mid - tree[L(C)].rmx + 1;
else return query(p, R(C));
}
struct Point
{
int bg, ed;
Point(){}
Point(int a, int b) {bg = a; ed = b;}
};
vector<Point>g;
int find(int x) //二分的目的是找到左界比x大的区间
{
int low = 0, high = g.size() - 1;
int mid;
while(low <= high)
{
mid = (low + high) >> 1;
if(g[mid].bg <= x) low = mid + 1;
else high = mid - 1;
}
return low;
}
int main()
{
int n, m, x;
char s[15];
while(scanf("%d%d", &n, &m) != EOF)
{
make_tree(1, n, 1);
g.clear();
while(m--)
{
scanf("%s", s);
if(s[0] == 'R')
{
tree[1].cover = 0;
tree[1].lmx = tree[1].rmx = tree[1].mx = n;
g.clear();
printf("Reset Now\n");
}
else if(s[0] == 'N')
{
scanf("%d", &x);
if(tree[1].mx < x)
printf("Reject New\n");
else
{
int t = query(x, 1);
printf("New at %d\n", t);
update(t, t + x - 1, 1, 1);
Point tmp(t, t + x - 1);
if(g.size() == 0) g.push_back(tmp);
else
{
int rt = find(t);
g.insert(g.begin() + rt, tmp);//插入操作
}
}
}
else if(s[0] == 'G')
{
scanf("%d", &x);
if(g.size() < x) printf("Reject Get\n");
else printf("Get at %d\n", g[x - 1].bg);
}
else if(s[0] == 'F')
{
scanf("%d", &x);
int rt = find(x) - 1;
if(rt == -1 || g[rt].ed < x)
printf("Reject Free\n");
else
{
printf("Free from %d to %d\n", g[rt].bg, g[rt].ed);
update(g[rt].bg, g[rt].ed, 0, 1);
g.erase(g.begin() + rt);//删除操作
}
}
}
puts("");
}
return 0;
}
分享到:
相关推荐
从简单入门到偏中等的几个题,线段树很灵活,主要懂了lazy操作,其他的自己yy吧。
hdu 1166线段树代码
hdu 1166线段树
【hdu5306】Gorgeous Sequence 线段树区间最值操作-附件资源
线段树入门资料,有利于初学者学习,让他们详细了解线段树。
300+ AC 代码 。 大数 , 线段树 , 字符串 , dp.....
杭电ACM课件2014版之(HDUACM2010版_13)二分匹配及其应用
hdu 1695 GCD(欧拉函数+容斥原理).docx
NULL 博文链接:https://128kj.iteye.com/blog/1738772
HDU二分匹配及其应用,此PPT是刘春英老师版权所有, 特此贡献给广大编程爱好者,特别是对于ACMer
大量线段树题目 zoj 1610 线段覆盖 poj 2777 线段覆盖 poj 2528 需要离散化,建树不同,需要处理不同->注意这组数据 3 1 10 1 3 6 10 the ans is 3. hdu 1754 求区间最大值 hdu 1166 求区间和 hdu 1698 成段更新 ...
HDU图论题目分类
hdu题目分类
ACM HDU题目分类,我自己总结的大概只有十来个吧
本人准备2020年保研机试时刷的题目(虽然最后机试取消了,...来自某中流985,在HDU和vjudge平台上大概刷了400道。本文件地图(excel表格)包含了绝大部分我刷过的题目,笔记中具有思路、代码、总结和心得。 大佬勿入!
ACM题库,一些题目和答案,以及解题报告,传上来共享
acm hdu as easy as a+b
HDU的1250,主要是利用高精度加法,但是代码有点繁琐,效率不是很高