HDU 4614 Vases and Flowers(线段树+二分)

题目链接

比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性。线段树中的lz标记很强大,这个题的题意也挺纠结的。

k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置,一个都没插,输出不能插。

k = 2时,将[a,b]区间都清空,输出这个区间上本来有多少朵花。

主要是k = 1的时候,很难弄。给出区间[a,b]要找到第一个空花瓶,空花瓶的个数 = 总的-插花的个数

这肯定是一个单增的,所以利用二分求下界,这个位置,就是第一个空花瓶的位置,最后一个花瓶的位置需要特判一下,确定是第几个空花瓶,剩下的跟算第一个差不多。

主要是很多细节要注意,写代码要各种严谨....

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <cstdlib>
  6 using namespace std;
  7 #define lson l,m,rt<<1
  8 #define rson m+1,r,rt<<1|1
  9 int sum[4*50001];
 10 int lz[4*50001];
 11 int n;
 12 void pushup(int rt)
 13 {
 14     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
 15 }
 16 void pushdown(int rt,int m)
 17 {
 18     if(lz[rt] == 1)
 19     {
 20         lz[rt<<1] = lz[rt];
 21         lz[rt<<1|1] = lz[rt];
 22         sum[rt<<1] = (m - (m>>1));
 23         sum[rt<<1|1] = (m>>1);
 24         lz[rt] = 0;
 25     }
 26     else if(lz[rt] == -1)
 27     {
 28         lz[rt<<1] = lz[rt];
 29         lz[rt<<1|1] = lz[rt];
 30         sum[rt<<1] = 0;
 31         sum[rt<<1|1] = 0;
 32         lz[rt] = 0;
 33     }
 34 }
 35 int query(int L,int R,int l,int r,int rt)
 36 {
 37     int m;
 38     int ans = 0;
 39     if(l >= L&&r <= R)
 40     {
 41         return sum[rt];
 42     }
 43     pushdown(rt,r-l+1);
 44     m = (l+r)>>1;
 45     if(L <= m) ans += query(L,R,lson);
 46     if(R > m) ans += query(L,R,rson);
 47     return ans;
 48 }
 49 void update(int L,int R,int sc,int l,int r,int rt)
 50 {
 51     int m;
 52     if(l >= L&&r <= R)
 53     {
 54         lz[rt] = sc;
 55         if(sc == 1)
 56         sum[rt] = (r - l + 1);
 57         else
 58         sum[rt] = 0;
 59         return ;
 60     }
 61     pushdown(rt,r-l+1);
 62     m = (l+r) >> 1;
 63     if(L <= m) update(L,R,sc,lson);
 64     if(R > m) update(L,R,sc,rson);
 65     pushup(rt);
 66 }
 67 int bis(int x,int key)
 68 {
 69     int str,end,mid,temp;
 70     str = x,end = n-1;
 71     if(end-x+1 - query(x,end,0,n-1,1) == 0)
 72     return -1;
 73     while(str < end)
 74     {
 75         mid = (str + end)/2;
 76         temp = (mid-x+1) - query(x,mid,0,n-1,1);
 77         if(temp < key)
 78         str = mid + 1;
 79         else
 80         end = mid;
 81     }
 82     return str;
 83 }
 84 int bin(int x,int key)
 85 {
 86     int str,end,mid,temp;
 87     str = x;end = n-1;
 88     temp = (n-x) - query(x,n-1,0,n-1,1);
 89     if(key > temp)
 90     key = temp;
 91     while(str < end)
 92     {
 93         mid = (str + end)/2;
 94         temp = (mid-x+1) - query(x,mid,0,n-1,1);
 95         if(temp < key)
 96         str = mid + 1;
 97         else
 98         end = mid;
 99     }
100     return str;
101 }
102 int main()
103 {
104     int t,m,i,a,b,k;
105     scanf("%d",&t);
106     while(t--)
107     {
108         scanf("%d%d",&n,&m);
109         memset(sum,0,sizeof(sum));
110         memset(lz,0,sizeof(lz));
111         for(i = 1;i <= m;i ++)
112         {
113             scanf("%d%d%d",&k,&a,&b);
114             if(k == 1)
115             {
116                 a = bis(a,1);
117                 if(a != -1)
118                 b = bin(a,b);
119                 if(a == -1)
120                 printf("Can not put any one.\n");
121                 else
122                 {
123                     printf("%d %d\n",a,b);
124                     update(a,b,1,0,n-1,1);
125                 }
126             }
127             else
128             {
129                 printf("%d\n",query(a,b,0,n-1,1));
130                 update(a,b,-1,0,n-1,1);
131             }
132         }
133         printf("\n");
134     }
135     return 0;
136 }

 

 

posted @ 2013-07-27 11:33  Naix_x  阅读(208)  评论(0编辑  收藏  举报