【Monotonic-queue】【dp】【Segment-tree】【STL】Codeforces 487B - Strip
来源:互联网 发布:ubuntu kylin 14.04 编辑:程序博客网 时间:2024/06/05 16:18
Codeforces 487B - Strip :http://codeforces.com/problemset/problem/487/B
Description:
Alexandra has a paper strip with n numbers on it. Let's call them ai from left to right.
Now Alexandra wants to split it into some pieces (possibly 1). For each piece of strip, it must satisfy:
- a、Each piece should contain at least l numbers.
- b、The difference between the maximal and the minimal number on the piece should be at most s.
Please help Alexandra to find the minimal number of pieces meeting the condition above.
The first line contains three space-separated integers n, s, l (1 ≤ n ≤ 105, 0 ≤ s ≤ 109, 1 ≤ l ≤ 105).
The second line contains n integers ai separated by spaces ( - 109 ≤ ai ≤ 109).
Output the minimal number of strip pieces.
If there are no ways to split the strip, output -1.
It's easy to understand what's the description talking about.
I had no idea when I first see the question.After a deep thought,an idea came to me and I began to write.I used a queue to record each condition.Almost each condition can expand into two conditions that led to Memory limit exceeded.The first submission was wrong.
Then I read the tutorial.The tutorial uses the method of dp using two arrays f[i] and g[i].
f[i] records how many pieces at least from the first item.But how to transform from smaller conditions?At first ,a piece should include at least l items.So k is at mosti-lif it's legal.Then,what's the left limit?It's decided by how long is legal as left as possible.It means that between k to i the biggest item minus the smallest item is less than or equal to s but between k-1 to i is not.
So we also need to find the left most position in accordance with condition b.
g[i] denote the maximal length of substrip whose right border is i(included) and it satisfy the condition.So k is at least i-g[i].
f[i]=min{ f[k] }+1 (i-g[i]<=k<=i-l)
The tutorial told me to use monotonic queue to solve g[i].I'm learning about monotonic queue,so I did it as tutorial.
I used two monotonic queues.One records the biggest item and the other records the smallest one.
The second submission was also wrong because I only recorded the position of the biggest and the smallest without recording other messages .So I modified my code adding two queues to record left most item .
The third submission was time limit exceeded.Because It would be O(n^2) if every g[i]=i.
For example,
100000 3 4
0 0 0 0 0 0 0 .....0
It's easy to get the answer which is one,but g[i] = {1,2,3,4,5,.....100000} so that each k is from 0 to i-4 for each i.
Actually,I don't know how to solve this problem.However,I just add a condition that when the biggest minus the smallest from i=1 to i=n,output 1 or -1 directly to avoid O(n^2)。It is accepted!Amazing!
I think it is because of lucky...
Now paste myugly accepted code.
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <fstream>using namespace std;//#define ll __int64#define ll long long#define L(u) ((u)<<1)#define R(u) ((u)<<1|1)#define lowbit(x) ((x)&-(x))#define PB push_back#define sq(x) ((x)*(x))#define rep(i,x,y) for(i=x;i<=y;i++)#define rep0(i,x,y) for(i=x;i<y;i++)#define mem(a, num) memset(a, num, sizeof(a))#define cpy(to, from) memcpy(to, from, sizeof(from))#define sd(x) scanf("%d",&x)#define sd2(x,y) scanf("%d%d",&x,&y)#define sd3(x,y,z) scanf("%d%d%d",&x,&y,&z)//#define slld(x) scanf("%I64d",&x)//#define slld2(x,y) scanf("%I64d%I64d",&x,&y)//#define slld3(x,y,z) scanf("%I64d%I64d%I64d",&x,&y,&z)#define slf(x) scanf("%lf",&x)#define slf2(x,y) scanf("%lf%lf",&x,&y)#define sc(c) scanf("%c",&c);#define ss(st) scanf("%s",st);#define pd(x) printf("%d\n",x);#define plld(x) printf("%I64d\n",x);#define pcas() printf("Case %d: ", ++cas)#define pn() putchar(10);#define SA(a,i,n) rep(i,1,n) sd(a[i])#define SA0(a, i, n) rep0(i,0,n) sd(a[i])#define PA(a,i,n) rep0(i,1,n) printf("%d ", a[i]); pd(a[(n)])#define PA0(a, i, n) rep0(i,0,(n)-1) printf("%d ", a[i]); pd(a[(n) - 1])#pragma comment(linker, "/STACK:102400000,102400000")const int N = 300;const int M = 100005;const int INF = 0x3f3f3f3f;const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;const double pi = acos(-1.0);int q1[M],q2[M],a[M],f[M],g[M];int p1[M],p2[M];int main(){ int n,s,l; while(scanf("%d%d%d",&n,&s,&l)!=EOF){ int maxx=-INF; int minn=INF; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); maxx=max(maxx,a[i]); minn=min(minn,a[i]); } if(maxx-minn<=s){ printf("%d\n",l<=n?1:-1); continue; } int be1=1,be2=1,end1=1,end2=1; for(int i=1;i<=n;i++){ int t1=i,t2=i; while(end1!=be1&&a[i]>=a[q1[end1-1]]){ t1=p1[--end1]; } q1[end1]=i; p1[end1++]=t1; while(end2!=be2&&a[i]<=a[q2[end2-1]]){ //end2--; t2=p2[--end2]; } p2[end2]=t2; q2[end2++]=i; while(be1<end1&&be2<end2&&a[q1[be1]]-a[q2[be2]]>s){ if(q1[be1]<q2[be2]){ be1++; } else if(q1[be1]>q2[be2]){ be2++; } else{ be1++; be2++; } } g[i]=i-max(p1[be1],p2[be2])+1; } f[1]=1; for(int i=2;i<=n;i++){ int minn=INF; for(int j=i-g[i];j<=i-l;j++){ if(f[j]<minn){ minn=f[j]; } } if(minn==INF) f[i]=INF; else f[i]=minn+1; } if(f[n]==INF) cout<<-1<<endl; else cout<<f[n]<<endl; } return 0;}
segment-tree+dp: http://www.tuicool.com/articles/Ar2eaa
There is a magic way using STL which is short.
STL: http://www.cnblogs.com/zyue/p/4360175.html
// File Name: 487b.1.cpp// Author: darkdream// Created Time: 2015年03月23日 星期一 15时24分56秒#include<vector>#include<list>#include<map>#include<set>#include<deque>#include<stack>#include<bitset>#include<algorithm>#include<functional>#include<numeric>#include<utility>#include<sstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cmath>#include<cstdlib>#include<cstring>#include<ctime>#define LL long long#define N 100007using namespace std;multiset<int> st,rt;int dp[N],n,l,s,a[N];int main(){ scanf("%d %d %d",&n,&s,&l); for(int i = 1;i <= n;i ++) scanf("%d",a+i); for(int i = 1,j = 1;i <= n;i ++) { st.insert(a[i]); for(;*st.rbegin() - *st.begin() > s;j ++) { st.erase(st.find(a[j])); if(i - j >= l) rt.erase(rt.find(dp[j-1])); } if(i - j + 1 >= l) rt.insert(dp[i-l]); if(rt.begin() == rt.end()) dp[i] = N; else dp[i] = *rt.begin() + 1; } printf("%d\n",dp[n] >= N?-1:dp[n]);return 0;}
- 【Monotonic-queue】【dp】【Segment-tree】【STL】Codeforces 487B - Strip
- codeforces 487B Strip dp
- 【DP】 codeforces 487B Strip
- CodeForces 487B Strip
- codeforces 487 B. Strip
- CodeForces 487B Strip
- Codeforces 487B. Strip DP+线段树+二分
- Codeforces 487b Strip, dp + RMQ(经典)
- CodeForces 487 B.Strip(dp+尺取+set)
- Codeforces 487B Strip(RMQ)
- Codeforces 487B. Strip(求区间最值+线段树上的dp)
- Codeforces Round #278 (Div. 1) B. Strip(Dp+multiset维护)
- codeforces 487B B. Strip(rmq+线段树+二分)
- 单调队列Monotonic Queue
- codeforces 274B Zero Tree(树形dp)
- codeforces 274B B. Zero Tree(树形dp)
- codeforces 461B B. Appleman and Tree(树形dp)
- Codeforces-242B-Big Segment
- VS2015 调试失败 提示拒绝访问解决方法
- jenkins 安装
- 用onkeyup来实现html输入框的协同变化
- VMware中虚拟机复制的问题
- 推荐10本C#编程的最佳书籍
- 【Monotonic-queue】【dp】【Segment-tree】【STL】Codeforces 487B - Strip
- codeforces 631B Print Check
- html布局练习
- Coursera上machine learning证书
- React概述
- [LeetCode] 335. Self Crossing
- 跟我一起写makefile------皓哥
- codeforces 631c Report
- python-列表推倒式-轻量级循环