两点法是通常用来求解简单的区间问题的O(n)算法,两点法顾名思义有两个点,一个起点一个终点,在区间上维护这两个点,动态更新题目要求的值的大小
这里举出NOJ两道较简单且有代表性的题,一道是数字一道是字符串
题目描述
女巫璐璐生活在美丽的仙林。璐璐突发奇想想到了炒股。璐璐运用了她的神奇魔法获取了一支股票未来连续N天的价格。
璐璐现在想知道从这N天里,哪天买入,哪天卖出可以使自己自己的收益最大。
输入
输入第一行是一个整数T,代表测试用例个数。接下来的每组数据第一行为一个整数N(2≤N≤100000),代表这支股票未来N天的价格,第二行为N个整数a1,a2,..aN。
输出
输出璐璐能得到的最大收益。如果璐璐无论怎么买入卖出都不能赚钱(收益大于0),输出0。
输出格式见样例,首先输出“Case #: ”,再输出答案,其中#表示第几个测试用例。
样例输入
3
3
3 2 1
3
1 2 3
3
2 3 1
样例输出
Case 1: 0
Case 2: 2
Case 3: 1
题目链接:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1972
题目分析:st,ed初始化为0,当a[st] < a[i]时说明是递增的,可卖出,所以更新ed和ans,否则,更新st,因为如果当前点后第二个点比当前点大,后第一个点比当前点小,显然应当把当前的后的那个点当作起点
#include <cstdio> #include <algorithm> using namespace std; int a[100005]; int main() { int T; scanf("%d", &T); for(int ca = 1; ca <= T; ca++) { int n, ans = 0; scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &a[i]); int st = 0, ed = 0; for(int i = 1; i < n; i++) { if(a[st] < a[i]) { ed = i; ans = max(ans, (a[ed] - a[st])); } else st = i; } printf("Case %d: %d\n", ca, ans); } }
题目描述
大学四事之娱乐生活。
Best Riven NUPT ,即南邮最强瑞文,作为一个LOSER,啊不,LOLER,BENBB一直向着这个目标努力练习着。
作为英雄联盟中最需要操作的几个英雄之一,一个优秀的瑞文玩家,需要掌握其特殊的连招技巧!瑞文的主要技能为QWER,加上A人和鼠标右键总计6种操作命令。这里我们把鼠标右键记作1。要想有效的在与敌人的较量中获得胜利,就需要在短时间内打出更多的伤害,即取消游戏中的前摇和后摇。具体方法如下:
在使用Q技能之后用鼠标右键可以取消Q的施法后摇。
在A之后使用Q技能能取消A的后摇。
在E技能之后使用W或者R可以取消施法前摇。
……
如此一来我们定义下BRN所需要的操作吧。
1、Q之后必须接上鼠标右键1。
2、A之后必须接上Q技能。
3、W和R之前必须是E技能。
4、R和W之后必须接上Q技能或者A。
5、其余技能可以随意连接
BENBB在练习中释放了很多次技能,现在请你找出其中最长的满足BRN需求的连招的长度。
输入
第一行为一个正整数T,表示有T组数据
每组为一行字符串(长度不超过10000,所有字母都为大写)
输出
每组单独一行输出一个正整数m代表最长BRN连招长度
样例输入
3
AQ1A
QWERA1
ERQ1AQ1EWAQ1111111ERA
样例输出
4
3
21
题目链接:http://acm.njupt.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1974
题目分析:运用两点法,当可以连击时更新ed,不能连击时更新st
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; char s[10000]; int main() { int T; scanf("%d", &T); while(T--) { scanf("%s", s); int len = strlen(s); int ans = 0, st = 0, ed = 0; for(int i = 0; i < len;) { ans = max(ans, ed - st + 1); if(s[i] == 'A' && s[i + 1] != 'Q' ) { i ++; st = i; } else if(s[i] == 'Q' && s[i + 1] != '1' ) { i ++; st = i; } else if((s[i + 1] == 'W' && s[i] != 'E')) { i ++; st = i; } else if((s[i + 1] == 'R' && s[i] != 'E')) { i ++; st = i; } else if(s[i] == 'R' && (s[i + 1] != 'Q' && s[i + 1] != 'A')) { i ++; st = i; } else if(s[i] == 'W' && (s[i + 1] != 'Q' && s[i + 1] != 'A')) { i ++; st = i; } else { i ++; ed = i; } } printf("%d\n", ans); } }
NOJ 1972 炒股票的女巫璐璐 && NOJ 1974 BRN (浅谈两点法)
原文:http://blog.csdn.net/tc_to_top/article/details/43855427