Codeforces Round #209 (Div. 2) D. Pair of Numbers
2013-11-12 17:28
369 查看
这题的技巧貌似非常经典,但是但是比赛的时候不会,所以没做出来,后来前天下午做了一下福州大学的有奖月赛,其中卡在一题上2.5小时,终于想出来了这个技巧,(完全自己YY),后来和同学交流发现这种技巧很经典,很常用,然后有点小开心,(哎高中没搞过OI,就是这么蛋疼,这个技巧都得自己YY。。。有个人点你一下也许会少花点时间,不过自己想出来的总是会更有成就感,理解也更透彻啦。。。)顺便联想到这题可以用这个技巧做,所以写篇日志记录一下。
题目链接:http://codeforces.com/contest/359/problem/D
说的是让你求一个长度最长的区间,使得这个区间里的每个数都能被这个区间里的某个数整除。n = 300000。
技巧就是快速预处理出对于每个数,以他作为那个除数,向左右两边延伸最远能到的区间的两端的下标值。这样再O(n)一遍求出区间最大值后面就简单了。
关键是如何很快预处理出来?普通方法是从这个数开始向两边尝试,显然会TLE。(所有数相同则退化到O(n^2))
我们考虑递推,(我当时就是这么直接想到了递推的,可能有点突兀,可能和我那几天在做KMP有关,KMP也是递推的思想很巧妙,所以吸收了一下),如何递推呢?我们分开处理左端点值和右端点值,设两个数组 l[i], r[i],假设在处理 l[i]前面的 l[x]都已经处理好了,那么首先看当前的 a[i] 能否被 a[i - 1]整除,如果不能那么l[i] 等于 i - 1,如果能被整除这时候前面的结果就有用了,首先从 i - 1往左到 l[i - 1] 区间里的这些数都能被 a[i]整除,(这应该很显然吧?)但是
a[l[i - 1]]不能被 a[i - 1] 整除,所以不知道a[i] 与 a[l[i - 1]]的整除关系,这时候再判断一次整除关系就可以了,这样我们就跳过了一些数的整除性的判断,算法时间复杂度下降了很多。如果有个数轴,你看到的应该就是我们在跳跃着判断一些数的整除关系,判断次数减少很多,对于右端点,我们也类似处理,唯一有点小变化就是从右往左进行,这应该不难理解吧?
最后代码如下:
这样做的时间复杂度是多少,我不会算,我猜是O(n)的(会不会是O(nlogn)?)有人能告诉我么?
另外是福州大学有奖月赛的这题,启发我的一题:http://acm.fzu.edu.cn/contest/problem.php?cid=130&sortid=5
这题除了这个小技巧之外还需要一个技巧的,当时也自己YY的,貌似和标准解法不一样。值得一做,不难啦。
题目链接:http://codeforces.com/contest/359/problem/D
说的是让你求一个长度最长的区间,使得这个区间里的每个数都能被这个区间里的某个数整除。n = 300000。
技巧就是快速预处理出对于每个数,以他作为那个除数,向左右两边延伸最远能到的区间的两端的下标值。这样再O(n)一遍求出区间最大值后面就简单了。
关键是如何很快预处理出来?普通方法是从这个数开始向两边尝试,显然会TLE。(所有数相同则退化到O(n^2))
我们考虑递推,(我当时就是这么直接想到了递推的,可能有点突兀,可能和我那几天在做KMP有关,KMP也是递推的思想很巧妙,所以吸收了一下),如何递推呢?我们分开处理左端点值和右端点值,设两个数组 l[i], r[i],假设在处理 l[i]前面的 l[x]都已经处理好了,那么首先看当前的 a[i] 能否被 a[i - 1]整除,如果不能那么l[i] 等于 i - 1,如果能被整除这时候前面的结果就有用了,首先从 i - 1往左到 l[i - 1] 区间里的这些数都能被 a[i]整除,(这应该很显然吧?)但是
a[l[i - 1]]不能被 a[i - 1] 整除,所以不知道a[i] 与 a[l[i - 1]]的整除关系,这时候再判断一次整除关系就可以了,这样我们就跳过了一些数的整除性的判断,算法时间复杂度下降了很多。如果有个数轴,你看到的应该就是我们在跳跃着判断一些数的整除关系,判断次数减少很多,对于右端点,我们也类似处理,唯一有点小变化就是从右往左进行,这应该不难理解吧?
最后代码如下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <cstring> #include <cctype> #include <set> #include <list> #include <stack> #include <queue> #include <deque> #include <string> #include <vector> #include <map> #include <iomanip> #include <ctime> #pragma warning (disable : 4996) #define mem(a) memset(a, 0, sizeof(a)) #define dou double #define LL long long #define N 311111 #define Mod 1000000007 #define sl(a) strlen(a) #define eps 1e-8 #define inf 1000000000 using namespace std; int a , l , r , cnt ; int main(){ int n, t, ca = 1, i, j, k, re, sum, tem, id = -1, st; //freopen("in,txt", "r", stdin); //freopen("out.txt", "w", stdout); ios :: sync_with_stdio(false); cin >> n; for (i = 1; i <= n; ++i) cin >> a[i], l[i] = i - 1, r[i] = i + 1; for (i = 1; i <= n; ++i){ tem = i; while (tem && a[l[tem]] % a[i] == 0) tem = l[tem]; l[i] = l[tem]; } for (i = n, r[n + 1] = n + 1; i >= 1; --i){ tem = i; while (tem <= n && a[r[tem]] % a[i] == 0) tem = r[tem]; r[i] = r[tem]; } //for (i = 1; i <= n; ++i) cout << l[i] << ' '; //cout << endl; //for (i = 1; i <= n; ++i) cout << r[i] << ' '; //cout << endl; for (i = 1; i <= n; ++i){ if (r[i] - l[i] > id) id = r[i] - l[i], st = l[i] + 1; } cnt[0] = st; for (i = st, j = 1; i <= n; ++i){ if (r[i] - l[i] == id && l[i] + 1 > st) cnt[j++] = l[i] + 1, st = l[i] + 1; } cout << j << ' ' << id - 2 << endl; for (i = 0; i < j; ++i) cout << cnt[i] << ' '; return 0; }
这样做的时间复杂度是多少,我不会算,我猜是O(n)的(会不会是O(nlogn)?)有人能告诉我么?
另外是福州大学有奖月赛的这题,启发我的一题:http://acm.fzu.edu.cn/contest/problem.php?cid=130&sortid=5
这题除了这个小技巧之外还需要一个技巧的,当时也自己YY的,貌似和标准解法不一样。值得一做,不难啦。
相关文章推荐
- 【CF 应用开发大赛】MZCMS内容管理系统
- windows 7 玩不了CF 打开之后进入安全登录就自动关闭
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- CF Round#2
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces 193 Div 2
- Codeforces Round #184 (Div. 2) D、E
- CodeForces - 329B 《Biridian Forest》 【反向BFS】
- CF # 92 (Div. 2 Only)
- codeforce round 175 div2
- Codeforces 336A【 Vasily the Bear and Triangle 】
- codeforces 363A round211 div2 A.Soroban
- codeforces 363B round211 div2 B. Fence
- CodeForces--320A--Magic numbers
- Codeforces230C--Shifts--想法题--类似palindrome
- codeforces227B--Effective Approach--想法题
- TC(SRM)和CF入门教程for ACMer
- CF DIV.2 A. The Wall