N个矩形,排成一排. 现在希望用尽量少的矩形海报Cover住它们.
N个矩形,排成一排. 现在希望用尽量少的矩形海报Cover住它们.
第一行给出数字N,代表有N个矩形.N在[1,250000] 下面N行,每行给出矩形的长与宽.其值在[1,1000000000]2 1/2 Postering
最少数量的海报数.
RMQ/单调栈。
如果两个矩形能同时被一个海报覆盖,要满足两个条件:
1.他俩的高度相同
2.他们之间的海报没有比他俩更矮的
先说我的做法:
用RMQ预处理出区间最小值,然后依次枚举即可。
但要注意一个问题,如果有好多个矩形高度相同,那么需要从每一个为起点,来进行判断,可行则跳出,不可行则继续枚举。
好麻烦。。
其实正解是单调栈。。
维护一个单调递增的栈(因为如果当前高度比之前小,那么之前的永远不可能满足要求了);
如果遇到和队尾相同的,那么使答案减1。
下面是我的RMQ代码(无视掉Solve()。。那是我的对拍)
#include <iostream> #include <algorithm> #include <cstring> #include <cstdlib> #include <cstdio> #define M 250005 using namespace std; int f[M][20],h[M],n; struct data { int x,p; }a[M]; void read(int &tmp) { tmp=0; char ch=getchar(); int fu=1; for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') fu=-1; for (;ch>='0'&&ch<='9';ch=getchar()) tmp=tmp*10+ch-'0'; tmp*=fu; } void RMQ() { for (int i=1;i<=n;i++) f[i][0]=h[i]; for (int j=1;(1<<j)<=n;j++) for (int i=1;i+(1<<j)-1<=n;i++) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } int Getlog(int x) { int now=1; for (int i=0;;i++) { now<<=1; if (now>=x) return i; } } int Getmin(int l,int r) { int k=Getlog(r-l+1); return min(f[l][k],f[r-(1<<k)+1][k]); } int Solve(int l,int r) { if (l==r) return 1; int ans=1; int m=Getmin(l,r); int cnt=0; for (int i=l;i<=r;i++) if (h[i]==m) cnt++; if (cnt==1) return r-l+1; int from=l; for (int i=l;i<=r;i++) if (h[i]==m) { if (from<i) ans+=Solve(from,i-1); from=i+1; } if (from<=r) ans+=Solve(from,r); return ans; } bool cmp(data a,data b) { if (a.x==b.x) return a.p<b.p; return a.x<b.x; } int main() { read(n); int x; for (int i=1;i<=n;i++) read(x),read(h[i]),a[i].x=h[i],a[i].p=i; RMQ(); sort(a+1,a+1+n,cmp); int now=1; int ans=n; while (now<=n) { int r=now; while (r+1<=n&&a[r+1].x==a[r].x) r++; int k=now+1; for (int i=now;i<r;i++) { if (k<=i) k=i+1; int j; for (j=k;j<=r;j++) { if (Getmin(a[i].p,a[j].p)==a[i].x) ans--; else {k=j;break;} } if (j>r) break; } now=r+1; } cout<<ans<<endl; return 0; }
#include<iostream> #include<cstdio> using namespace std; int t,x,n,s[250001],top,ans; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&t,&x); while(x<=s[top]) { if(x==s[top])ans++; top--; } s[++top]=x; } printf("%d",n-ans); return 0; }
单调栈写起来有简单速度又快。。关键是抓住两者之间不能有比他们矮的这个条件。
原文地址:http://blog.csdn.net/regina8023/article/details/43956319