Codeforces 573B Bear and Blocks

http://codeforces.com/problemset/problem/573/B

 题目大意:

给出n个连续塔,每个塔有高度hi,每次取走最外层的块,问需要多少次操作能够拿光所有的块。

思路:考虑第一次取得时候

h[i]=min(h[i-1],h[i]-1,h[i+1])

那么取k次的时候:

h[i]=max(0,min(h[i-j]-(k-j),h[i+j]-(k-j)))

h[i]=max(0,min(h[i-j]+j-k,h[i+j]+j-k))

k为常数,可以先暂时忽略,那就是要求h[i-j]+j和h[i+j]+j的最小值。

然后两遍左右for一下,同时给区间加一

 

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 struct segtree{
 7     int l,r,mn,tag;
 8 }t[5000005];
 9 int h[200005],n,l[200005],r[200005];
10 int read(){
11     int t=0,f=1;char ch=getchar();
12     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
13     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
14     return t*f;
15 }
16 void pushdown(int k,int l,int r){
17     if (l==r||t[k].tag==0){
18         return;
19     }
20     t[k*2].tag+=t[k].tag;
21     t[k*2].mn+=t[k].tag;
22     t[k*2+1].tag+=t[k].tag;
23     t[k*2+1].mn+=t[k].tag;
24     t[k].tag=0;
25 }
26 void updata(int k,int l,int r){
27     if (l==r) return;
28     t[k].mn=std::min(t[k*2].mn,t[k*2+1].mn);
29 }
30 void build(int k,int l,int r){
31     t[k].mn=0;
32     t[k].tag=0;
33     if (l==r){
34         t[k].mn=h[l];
35         return;
36     }
37     int mid=(l+r)>>1;
38     build(k*2,l,mid);
39     build(k*2+1,mid+1,r);
40     updata(k,l,r);
41 }
42 void add(int k,int l,int r,int x,int y){
43     pushdown(k,l,r);
44     if (l==x&&r==y){
45         t[k].mn++;
46         t[k].tag++;
47         pushdown(k,l,r);
48         return;
49     }
50     int mid=(l+r)>>1;
51     if (y<=mid) add(k*2,l,mid,x,y);
52     else
53     if (x>mid) add(k*2+1,mid+1,r,x,y);
54     else add(k*2,l,mid,x,mid),add(k*2+1,mid+1,r,mid+1,y);
55     updata(k,l,r);
56 }
57 int query(int k,int l,int r,int x,int y){
58     pushdown(k,l,r);
59     if (l==x&&r==y) return t[k].mn;
60     int mid=(l+r)>>1;
61     if (y<=mid) return query(k*2,l,mid,x,y);
62     else
63     if (x>mid) return query(k*2+1,mid+1,r,x,y);
64     else return std::min(query(k*2,l,mid,x,mid),query(k*2+1,mid+1,r,mid+1,y));
65 }
66 int main(){
67     n=read();
68     for (int i=1;i<=n;i++) h[i]=read();
69     h[0]=h[n+1]=0;
70     build(1,0,n+1);
71     for (int i=1;i<=n;i++){
72         add(1,0,n+1,0,i-1);
73         l[i]=query(1,0,n+1,0,i);
74     }
75     build(1,0,n+1);
76     for (int i=n;i>=1;i--){
77         add(1,0,n+1,i+1,n+1);
78         r[i]=query(1,0,n+1,i,n+1);
79     }
80     int ans=0;
81     for (int i=1;i<=n;i++)
82      ans=std::max(ans,std::min(l[i],r[i]));
83     printf("%d\n",ans); 
84     return 0;
85 }

 换种思路:我们的每一个竖列,要嘛在旁边两列消掉以后,一次性消掉,或者是一个一个地消

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<iostream>
 6 int n,vis[200005];
 7 int read(){
 8     int t=0,f=1;char ch=getchar();
 9     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
10     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
11     return t*f;
12 }
13 int main(){
14     n=read();
15     for (int i=1;i<=n;i++) vis[i]=read();
16     vis[1]=1;
17     for (int i=2;i<=n;i++) vis[i]=std::min(vis[i],vis[i-1]+1);
18     vis[n]=1;
19     for (int i=n-1;i>=1;i--) vis[i]=std::min(vis[i],vis[i+1]+1);
20     int ans=0;
21     for (int i=1;i<=n;i++) ans=std::max(ans,vis[i]);
22     printf("%d\n",ans);
23     return 0;
24 }

 

 

 

posted @ 2016-06-30 10:52  GFY  阅读(271)  评论(0编辑  收藏  举报