Pla

Pla(jdoj1006)

    题目大意:给你n个矩形,并排放在一起,你的目的是将所有的矩形全部染色。你每次染的形状为一个矩形,问:最少需要染多少次?

    注释:n<=10^6,wi , hi<=2^31-1,其中,wi和hi分别是矩形的宽和高。

      想法:第一想法是贪心,显然是不对的。在此,我们介绍一种数据结构——单调栈。顾名思义,就是维护栈里的元素是单调的。那么,在本题中,我们维护一个单调栈,每次加入一个数,判断栈顶,如果栈顶大于该数,则弹出,贡献+1,如果小于等于该数,则将该数压如栈内。最后,统计栈内元素个数,相同高度视为一种元素,贡献+=元素个数。

      下面,我们证明,为什么这玩意儿是对的。

      首先,先观察每次操作。如果压入的元素小于栈顶,我们设栈顶元素为h,除栈顶外的第一个元素的高度是 h - a ,想压入的元素的高度为 h - b ,那么,无论如何,栈顶高度的 min ( a , b ) 必须需要一次单独的染色。所以,这时,对于答案的贡献+1。然后,将栈顶元素的 a 染色,此时,剩余的高度与除栈顶外的第一个元素的高度是相同的,我们将它们视为一个元素,即——弹出。以此类推...最后,我们在栈中剩下的元素都是不相同的,这样,必须在需要元素个数次染色。

      最后,附上丑陋的代码......

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int a[100100];
 5 int top=0;
 6 int main()
 7 {
 8     int n;
 9     int w,h;//宽与高,显然发现,宽在本题中是没有地位的
10     scanf("%d",&n);
11     int ans=0;
12     for(int i=1;i<=n;i++)
13     {
14         scanf("%d%d",&w,&h);
15         a[++top]=h;//存高
16         while(1)//将元素压入栈中,并执行我们已经证明过的操作。
17         {
18             if(a[top]>a[top-1]) break;
19             else if(a[top]-a[top-1]==0)//在相等时,我们只需把栈顶元素弹出即可
20             {
21                 top--;
22             }
23             else
24             {
25                 top--;
26                 a[top]=h;
27                 ans++;
28             }
29         }
30     }
31     printf("%d",ans+top);//统计栈内剩余元素个数,即可
32     return 0;
33 }

      小结:错误

          1.没有判断相等,但不至于爆蛋。

          2.一直在裸贪心,不会转换想法。

          3.这与NOIP の某道T1类似,但是那道题被我dp驶过,不赘述。

    转载请注明:http://www.cnblogs.com/ShuraK/p/7853155.html

posted @ 2017-11-17 19:19  JZYshuraK_彧  阅读(321)  评论(0编辑  收藏  举报