尺取法:
又叫做滑动窗口。顾名思义,像尺子一样取一段。通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。之所以需要掌握这个技巧,是因为尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的。说到底,还是一种比较高效的枚举方法。
1、什么情况下能使用尺取法?
2、何时推进区间的端点?
3、如何推进区间的端点?
3、何时结束区间的枚举?
尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行判断之后,我们可以明确如何进一步有方向地推进区间端点以求解满足条件的区间,如果已经判断了目前所选取的区间,但却无法确定所要求解的区间如何进一步得到根据其端点得到,那么尺取法便是不可行的。首先,明确题目所需要求解的量之后,区间左右端点一般从最整个数组的起点开始,之后判断区间是否符合条件在根据实际情况变化区间的端点求解答案。
set函数:
set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值。
set的各成员函数列表如下:
1. begin()--返回指向第一个元素的迭代器
2. clear()--清除所有元素
3. count()--返回某个值元素的个数
4. empty()--如果集合为空,返回true
5. end()--返回指向最后一个元素的迭代器
6. equal_range()--返回集合中与给定值相等的上下限的两个迭代器
7. erase()--删除集合中的元素
8. find()--返回一个指向被查找到元素的迭代器
9. get_allocator()--返回集合的分配器
10. insert()--在集合中插入元素
11. lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
12. key_comp()--返回一个用于元素间值比较的函数
13. max_size()--返回集合能容纳的元素的最大限值
14. rbegin()--返回指向集合中最后一个元素的反向迭代器
15. rend()--返回指向集合中第一个元素的反向迭代器
16. size()--集合中元素的数目
17. swap()--交换两个集合变量
18. upper_bound()--返回大于某个值元素的迭代器
19. value_comp()--返回一个用于比较元素间的值的函数
例题
UVA 11572 |
题目大意:给你一段数字序列,从序列里取出一段子序列,要求子序列里没有重复的数字,让你求出子序列最大的长度是多少?
解决方法:尺取法,设l r ans ,根据贪心 r能取多大取多大,每次验证一下,如果不满足l++,在重复上一步,一直循环下去,直到r>=n
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<cmath>
#include<iostream>
using namespace std;
const int maxx=1e6+10;
int a[maxx];
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
set<int>s;
int L=1,R=1,ans=0;
while(R<=n)
{
while(R<=n&&!s.count(a[R]))
s.insert(a[R++]);
ans=max(ans,R-L);
s.erase(a[L++]);
}
printf("%d\n",ans);
}
return 0;
}