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)==1) return 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)==1) return 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 }
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)==1) return 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)==1) return 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 }