刷刷水题

来源:互联网 发布: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;}

趁还没崩,赶快退出

0 0