刷刷水题
来源:互联网 发布:mac os 镜像 编辑:程序博客网 时间:2024/04/30 10:46
uva11572
这题有坑。。。
输入一个长度为n的序列A,找一个长度尽量长的连续子序列AL ~ AR, 使得该序列中没有相同的元素。
我们可以滑动窗口,每次left 往右移动一次或者 right往右移动一格,判断a[right]是否在窗口中即可。判断是否在窗口中可以用set。这样整个程序的复杂度是O(n * log n)
/* * * Author : Triose * Email : Triose@163.com * Update_time : 2016.9.11 * *///#include<bits/stdc++.h>#include <map>#include <set>#include <queue>#include <stack>#include <string>#include <vector>#include <math.h>#include <time.h>#include <bitset>#include <iomanip>#include <stdio.h>#include <sstream>#include <iostream>#include <string.h>#include <iterator>#include <stdlib.h>#include <algorithm>using namespace std;#define READFILE#define eps 1e-8#define inf 0x3f3f3f3f#define INF 0x7fffffff#define INFL 0x3f3f3f3f3f3f3f3fLL#define enter putchar(10)#define rep(i,a,b) for(int i = (a); i < (b); ++i)#define per(i,a,b) for(int i = (a); i >= (b); --i)#define repe(i,a,b) for(int i = (a); i <= (b); ++i)#define ECH(it, A) for (typeof(A.begin()) it=A.begin(); it != A.end(); ++it)#define PR(a,b) pair<a,b>#define slen(str) strlen(str)#define ds(t) int t; sf(t)#define Down(t) while(t--)#define dc(t) int t; cin >> t;#define dsD(t) ds(t); Down(t)#define dcD(t) dc(t); Down(t)#define ALL(A) A.begin(), A.end()#define sf(a) scanf("%d",&a)#define sfI(a) scanf("%I64d",&a)#define sfd(a,b) scanf("%d%d",&a,&b)#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)#define scpy(str1, str2) strcpy(str1, str2)#define sfs(a) scanf("%s",a)#define pf(a) printf("%d\n",a)#define pfd(a,b) printf("%d %d\n",a,b)#define pfP(a) printf("%d %d\n",a.fi,a.se)#define pfs(a) printf("%s\n",a)#define pfI(a) printf("%I64d\n",a)#define mem(a,b) memset((a),b,sizeof(a))#define fi first#define se second#define LL long long#define DB double#define isws ios::sync_with_stdio(false)const double PI = acos(-1.0);const double E = exp(1.0);template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }template<class T> inline T Min(T a, T b) { return a < b ? a : b; }template<class T> inline T Max(T a, T b) { return a > b ? a : b; }/*******************************头文件到此结束******************************/int n, m;vector<int> a;set<int> exist;void Init() { exist.clear(); a.clear(); sf(n); rep(i, 0, n) sf(m), a.push_back(m);}int solve() { if(!n) return 0;//可能为0 int max_len = 1; int i = 0, j = 1; exist.insert(a[i]); while(j < n) { if(!exist.count(a[j])) { max_len = Max(max_len, j - i + 1); exist.insert(a[j++]); } else { exist.erase(a[i++]); } if(i == j) exist.insert(a[j++]); //当 i == j, 记得把a[j]放入,并且j++ } return max_len;}int main() {#ifndef ONLINE_JUDGE freopen("in.txt","r",stdin);// freopen("Out.txt", "w", stdout);#endif dsD(t) { Init(); pf(solve()); } return 0;}
由上一题引出了滑动窗口的最小值问题,描述如下:
输入一个正整数k和长度为n的整数序列A1, A2, A3….An, 定义f[i]为从元素i开始的连续k个元素中的最小值。输出f[1] ~ f[n - k + 1]
最简单的办法,对于每一个i,遍历从i开始的k个数,找到最小值更新。这样一来复杂度会是O((n - k) * k),要我出题肯定卡这个。
那么我们想办法优化一下。(n - k)反正没得优化了,看看这个k有没有办法。
可以考虑先求出f[1],把f[1] ~ f[1 + k - 1]放入一个multiset s中形成一个窗口。接下来就是这么一个过程,i 从 2 ~ n - k - 1, 每次擦除a[i - 1], 放入a[i + k - 1]形成了属于a[i]的窗口,并且multiset 是有序容器(由小到大排列),(s.begin())就是窗口中的最小值。移除的时候考虑到可能窗口里存在多个相同值,所以需要一个迭代器数组维护a[i]在集合中的地址。这样一来时间复杂度就优化到了O((n - k) log k) (毕竟滑动窗口是(n - k)而插入删除是O(log k))。
既然说到了数据结构能在不改变主算法的前提下提高程序效率,考虑是否有更加优化的数据结构。
有的,单调队列。
考虑到一个事实,假设现在窗口覆盖了4个元素分别是: 5 9 11 2(从左到右), 那么在2之前的5 9 11,在移出窗口前永远都不会成为最小值,那么它们就是无用的。窗口的数据结构理论上可以只存2这一个数字。那么我们可以构造这么一种数据结构(单调队列):(满足以下三个条件)
1、队首必须是整个队列中最小的元素。
2、新添加的值放入队尾。
3、若队首元素的值比队尾大,pop掉
这样的数据结构可以用STL实现,在deque的基础上实现。这里不细数。
qnmdCSDN,写一篇博客崩了2次还没有自动保存,你搞毛线啊!
我不写详解了,uva 1471贴代码了:
/* * * Author : Triose * Email : Triose@163.com * Update_time : 2016.9.11 * *///#include<bits/stdc++.h>#include <map>#include <set>#include <queue>#include <stack>#include <string>#include <vector>#include <math.h>#include <time.h>#include <bitset>#include <iomanip>#include <stdio.h>#include <sstream>#include <iostream>#include <string.h>#include <iterator>#include <stdlib.h>#include <algorithm>using namespace std;#define READFILE#define eps 1e-8#define inf 0x3f3f3f3f#define INF 0x7fffffff#define INFL 0x3f3f3f3f3f3f3f3fLL#define enter putchar(10)#define rep(i,a,b) for(int i = (a); i < (b); ++i)#define per(i,a,b) for(int i = (a); i >= (b); --i)#define repe(i,a,b) for(int i = (a); i <= (b); ++i)#define ECH(it, A) for (typeof(A.begin()) it=A.begin(); it != A.end(); ++it)#define PR(a,b) pair<a,b>#define slen(str) strlen(str)#define ds(t) int t; sf(t)#define Down(t) while(t--)#define dc(t) int t; cin >> t;#define dsD(t) ds(t); Down(t)#define dcD(t) dc(t); Down(t)#define ALL(A) A.begin(), A.end()#define sf(a) scanf("%d",&a)#define sfI(a) scanf("%I64d",&a)#define sfd(a,b) scanf("%d%d",&a,&b)#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)#define scpy(str1, str2) strcpy(str1, str2)#define sfs(a) scanf("%s",a)#define pf(a) printf("%d\n",a)#define pfd(a,b) printf("%d %d\n",a,b)#define pfP(a) printf("%d %d\n",a.fi,a.se)#define pfs(a) printf("%s\n",a)#define pfI(a) printf("%I64d\n",a)#define mem(a,b) memset((a),b,sizeof(a))#define fi first#define se second#define LL long long#define DB double#define isws ios::sync_with_stdio(false)const double PI = acos(-1.0);const double E = exp(1.0);template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }template<class T> inline T Min(T a, T b) { return a < b ? a : b; }template<class T> inline T Max(T a, T b) { return a > b ? a : b; }/*******************************???????******************************/int n, m;const int maxn = 200010;struct Node { int value, f, g; Node(int v = 0, int f_ = 0, int g_ = 0):value(v), f(f_), g(g_){} friend bool operator < (Node a, Node b) { return a.value < b.value; }};Node a[maxn];void Init() { sf(n); rep(i, 0, n) sf(a[i].value), a[i].f = a[i].g = 1; rep(i, 1, n) if(a[i].value > a[i - 1].value) a[i].g = a[i - 1].g + 1; per(i, n - 2, 0) if(a[i].value < a[i + 1].value) a[i].f = a[i + 1].f + 1;}set<Node> s;set<Node>::iterator fd;int solve() { int maxlen = 1; s.clear(); s.insert(a[0]); rep(i, 1, n) { fd = s.lower_bound(a[i]); bool keep = true; if(fd != s.begin()) { fd--; maxlen = Max(maxlen, fd->g + a[i].f); if(fd->g >= a[i].g) keep = false; } if(keep) { s.erase(a[i]); s.insert(a[i]); fd = s.find(a[i]); fd++; while(fd != s.end() && fd->g <= a[i].g && fd->value > a[i].value) s.erase(fd++); }// if(fd != s.begin()) fd--;// maxlen = Max(maxlen, fd->g + a[i].f);// if(fd->g < a[i].g) {// s.erase(a[i]); s.insert(a[i]);// fd = s.find(a[i]); fd++;// while(fd != s.end() && fd->g <= a[i].g && fd->value > a[i].value) s.erase(fd++);// } } return maxlen;}int main() {#ifndef ONLINE_JUDGE freopen("in.txt","r",stdin);// freopen("out.txt", "w", stdout);#endif dsD(t) { Init(); pf(solve()); } return 0;}
趁还没崩,赶快退出
- 刷刷水题
- 刷刷笔试题~~[递归]
- 刷刷笔试题~~[概率]
- 刷刷笔试题~~[数组]
- 刷刷笔试题~~[sql]
- 刷刷笔试题~~ [Java]
- 刷刷笔试题~~[矩阵]
- 刷刷笔试题~~[操作系统!!!]
- 剑指offer刷刷题
- 刷刷笔试题~(1)
- 刷刷笔试题~(2)
- 刷刷笔试题~~(3)
- 刷刷笔试题~~~[动态规划!!!!]
- 刷刷编程基础题~(1)
- 刷刷笔试题~!![二叉树]
- 刷刷笔试题--贪心算法
- 刷刷笔试题--[链表类编程]
- 刷刷笔试题~~[回溯法]
- Struts_SQLQuery
- 原生态Ajax写法异步提交,巧妙利用innerHTML实现不清空原来内容追加请求结果
- SpringMVC拦截器(资源和权限管理)
- base64解码urlencode乱码
- JavaScript_基础_事件
- 刷刷水题
- php实现远程下载图片
- javascript拼图算法
- poj 3592 Instantaneous Transference (借助强连通分量求缩点在建图spfa求最长路)
- 证明碰撞集(HITTING SET)问题是NP完全问题
- java学习日记_90:异常处理
- kibana 4.5.0安装
- 霍夫变换详解
- java并发编程——读写锁