hdu 4614 Vases and Flowers(线段树加二分查找)

周赛题

  1 /*
  2 线段树+二分查找
  3 处理比较麻烦,关键在用二分查找配合query()操作找从左往右第一个0和从右往左第一个0
  4 
  5 卡到的地方:
  6 1、区间更新不熟练
  7 2、关键点没想到
  8 3、低级错误位运算<<写成>>
  9 */
 10 #include <cstdio>
 11 #include <cstring>
 12 #define N 50005
 13 #define lson l,m,rt<<1
 14 #define rson m+1,r,rt<<1|1
 15 
 16 int emp[N<<2]; //0-区间下全为0,1-区间下全为1, 2-区间下不纯
 17 
 18 void build(int l, int r, int rt)
 19 {
 20     emp[rt] = 0;
 21     if(l==r) return;
 22     int m = (l + r) >> 1;
 23     build(lson);
 24     build(rson);
 25 }
 26 
 27 //s: 置0-空瓶 置1-摆花
 28 void update(int s, int a, int b, int l, int r, int rt)
 29 {
 30     int m = (l + r) >> 1;
 31     //不在范围内,不更新
 32     if(l>b || r<a) return;
 33     if(emp[rt]==s) return;
 34     if(emp[rt]==2)
 35     {
 36         if(a<=l && r<=b)
 37         {
 38             emp[rt] = s;
 39             return ;
 40         }
 41         update(s,a,b,lson);
 42         update(s,a,b,rson);
 43     }
 44     else
 45     {
 46         if(a<=l && r<=b)
 47         {
 48             emp[rt] = s;
 49             return ;
 50         }
 51         emp[rt<<1] = emp[rt];
 52         emp[rt<<1|1] = emp[rt];
 53         emp[rt] = 2;
 54         update(s,a,b,lson);
 55         update(s,a,b,rson);
 56     }
 57 }
 58 
 59 //查询a-b有多少个s(0或1)
 60 int query(int s, int a, int b, int l, int r, int rt)
 61 {
 62     if(l>b || r<a) return 0;
 63     int m = (l + r) >> 1;
 64     if(emp[rt]==s)
 65     {
 66         if(a<=l && r<=b)
 67             return r - l + 1;
 68         emp[rt<<1] = emp[rt];
 69         emp[rt<<1|1] = emp[rt];
 70         return query(s, a, b, lson) + query(s, a, b, rson);
 71     }
 72     else if(emp[rt]==2)
 73     {
 74         return query(s, a, b, lson) + query(s, a, b, rson);
 75     }
 76     else
 77         return 0;
 78 
 79 }
 80 
 81 //a-b从左往右找第一个0
 82 int bs(int a, int b, int num, int n)
 83 {
 84     int l = a, r = b, m;
 85     while(l<=r)
 86     {
 87         m = (l + r) / 2;
 88         int tmp = query(0, a, m, 1, n, 1);
 89         //printf("Loop-m:%d tmp:%d\n",m,tmp);
 90         if(tmp==num && query(0,m,m,1,n,1)==1return m;
 91         else if(tmp<num) l = m + 1;
 92         else r = m - 1;
 93     }
 94     return l;
 95 }
 96 
 97 //a-b中右到左找第一个0
 98 int bsright(int a, int b, int n)
 99 {
100     int l = a, r = b, m;
101     while(l<=r)
102     {
103         m = (l + r) / 2;
104         int tmp = query(0, m, b, 1, n, 1);
105         //printf("Loop-m:%d tmp:%d\n",m,tmp);
106         if(tmp==1 && query(0,m,m,1,n,1)==1return m;
107         else if(tmp<1) r = m - 1;
108         else l = m + 1;
109     }
110     return r;
111 }
112 
113 int main()
114 {
115     int t, n, m, a, b, k;
116     scanf("%d",&t);
117     while(t--)
118     {
119         scanf("%d%d",&n,&m);
120         build(1,n,1);
121         while(m--)
122         {
123             scanf("%d%d%d",&k,&a,&b);
124             if(k==2)
125             {
126                 a++; b++;
127                 printf("%d\n",query(1,a,b,1,n,1));
128                 update(0,a,b,1,n,1);
129 
130             }
131             else if(k==1)
132             {
133                 a++;
134                 int tmp = query(0,a,n,1,n,1);
135                 if(tmp==0)
136                 {
137                     printf("Can not put any one.\n");
138                 }
139                 else if(tmp<b)
140                 {
141                     //printf("postmp:%d\n",bs(a,n,tmp,n));
142                     printf("%d %d\n",bs(a,n,1,n)-1,bsright(a,n,n)-1);
143                     update(1,a,n,1,n,1);
144                 }
145                 else
146                 {
147                     int bb = bs(a,n,b,n);
148                     printf("%d %d\n",bs(a,n,1,n)-1,bsright(a,bb,n)-1);
149                     update(1,a,bb,1,n,1);
150                 }
151 
152             }
153         }
154         printf("\n");
155     }
156     return 0;
157 }
posted @ 2014-03-28 19:51  byluoluo  阅读(199)  评论(0编辑  收藏  举报