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 }