kb-07线段树-12--二分查找区间边界
1 /* 2 hdu4614 3 本题刚开始想能不能记录该区间最前面开始的点,最后面的点,区间空的数量;但是病不行 4 然后线段树的本质是区间操作,所以!这题主要就是区间的空的全放满,只要定出区间的边界就好办了; 5 这里用二分查找的方法,现计算满足数量的区间的尾,因为头已经确定了,及时不放花也是确定的,只要靠数量定出尾就可以了; 6 然后就是区间修改了; 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #include<algorithm> 12 #define MAX_N 50001 13 using namespace std; 14 int n,m,first,last,num,x; 15 struct tree 16 { 17 int l,r,fir,las,s,same,val; 18 }tr[MAX_N*4]; 19 void build(int rt,int l,int r) 20 { 21 tr[rt].l=l;tr[rt].r=r; 22 tr[rt].fir=l; 23 tr[rt].las=r; 24 tr[rt].s=0; 25 tr[rt].val=r-l+1; 26 if(l==r) 27 { 28 tr[rt].same=0; 29 return ; 30 } 31 tr[rt].same=1; 32 int mid=(l+r)/2; 33 build(rt<<1,l,mid); 34 build(rt<<1|1,mid+1,r); 35 } 36 void Pushup(int rt) 37 { 38 int l=rt<<1,r=rt<<1|1; 39 if(tr[l].fir==0) 40 tr[rt].fir=tr[r].fir; 41 else tr[rt].fir=tr[l].fir; 42 if(tr[r].las==0) 43 tr[rt].las=tr[l].las; 44 else tr[rt].las=tr[r].las; 45 tr[rt].val=tr[r].val+tr[l].val; 46 47 } 48 void Pushdown(int rt) 49 { 50 if(tr[rt].l==tr[rt].r) 51 return ; 52 int l=rt<<1,r=rt<<1|1; 53 if(tr[rt].same) 54 { 55 if(tr[rt].s==1) 56 { 57 tr[r].val=tr[l].val=0; 58 tr[r].s=tr[l].s=1; 59 tr[r].fir=tr[l].fir=0; 60 tr[r].las=tr[l].las=0; 61 tr[r].same=tr[l].same=1; 62 tr[rt].same=0; 63 } 64 else 65 { 66 tr[r].val=tr[r].r-tr[r].l+1; 67 tr[l].val=tr[l].r-tr[l].l+1; 68 tr[r].s=tr[l].s=0; 69 tr[r].same=tr[l].same=1; 70 tr[r].fir=tr[r].l; 71 tr[r].las=tr[r].r; 72 tr[l].fir=tr[l].l; 73 tr[l].las=tr[l].r; 74 tr[rt].same=0; 75 } 76 } 77 } 78 void Update1(int rt,int l,int r) 79 { 80 if(x<=0) 81 return ; 82 if(tr[rt].val==0) 83 return ;//在二分查找定区间后,少了这一句所以一直tle 84 if(tr[rt].l==l&&tr[rt].val>0) 85 { 86 if(first==0) 87 first=tr[rt].fir; 88 if(tr[rt].val<=x) 89 { 90 if(last<tr[rt].las) 91 last=tr[rt].las; 92 x-=tr[rt].val; 93 tr[rt].same=1; 94 tr[rt].s=1; 95 tr[rt].val=0; 96 tr[rt].fir=0; 97 tr[rt].las=0; 98 return ; 99 } 100 } 101 if(tr[rt].l==tr[rt].r) 102 return ; 103 Pushdown(rt); 104 int L=rt<<1,R=rt<<1|1; 105 if(l<=tr[L].r) 106 { 107 if(r<=tr[L].r) 108 Update1(L,l,r); 109 else 110 Update1(L,l,tr[L].r); 111 } 112 if(r>=tr[R].l) 113 { 114 if(l>=tr[R].l) 115 Update1(R,l,r); 116 else 117 Update1(R,tr[R].l,r); 118 } 119 Pushup(rt); 120 } 121 void Update2(int rt,int l,int r) 122 { 123 if(tr[rt].l==l&&tr[rt].r==r) 124 { 125 num+=r-l+1-tr[rt].val; 126 tr[rt].val=r-l+1; 127 tr[rt].s=0; 128 tr[rt].same=1; 129 tr[rt].fir=l; 130 tr[rt].las=r; 131 return; 132 } 133 if(tr[rt].l==tr[rt].r) 134 return ; 135 Pushdown(rt); 136 int L=rt<<1,R=rt<<1|1; 137 if(l<=tr[L].r) 138 { 139 if(r<=tr[L].r) 140 Update2(L,l,r); 141 else 142 Update2(L,l,tr[L].r); 143 } 144 if(r>=tr[R].l) 145 { 146 if(l>=tr[R].l) 147 Update2(R,l,r); 148 else 149 Update2(R,tr[R].l,r); 150 } 151 Pushup(rt); 152 } 153 int sum(int rt,int l,int r) 154 { 155 if(tr[rt].l==l&&tr[rt].r==r) 156 { 157 return tr[rt].val; 158 } 159 int ans=0; 160 Pushdown(rt);//因为只是查询,所以区间整体并没有变,就没有必要pushup了; 161 int L=rt<<1,R=rt<<1|1; 162 if(l<=tr[L].r) 163 { 164 if(r<=tr[L].r) 165 ans+= sum(L,l,r); 166 else 167 ans+= sum(L,l,tr[L].r); 168 } 169 if(r>=tr[R].l) 170 { 171 if(l>=tr[R].l) 172 ans+= sum(R,l,r); 173 else 174 ans+= sum(R,tr[R].l,r); 175 } 176 return ans; 177 } 178 int bisearch(int a,int f) 179 { 180 if(sum(1,a,n)==0) 181 return -1; 182 if(sum(1,a,n)<f)//此处的等于号的问题; 183 return n; 184 int l=a,r=n; 185 int ans=a; 186 while(l<=r) 187 { 188 int mid=(l+r)/2; 189 if(sum(1,a,mid)>=f)//以及此处的等于号; 190 { 191 ans=mid;//这里ans的取值; 192 r=mid-1; 193 } 194 else l=mid+1; 195 } 196 return ans; 197 } 198 int main() 199 { 200 int T; 201 scanf("%d",&T); 202 while(T--) 203 { 204 scanf("%d%d",&n,&m); 205 build(1,1,n); 206 for(int i=0;i<m;i++) 207 { 208 int ty,z,y; 209 scanf("%d%d%d",&ty,&z,&y); 210 if(ty==1) 211 { 212 int t=bisearch(z+1,y); 213 if(t!=-1) 214 { 215 x=y; 216 first=0; 217 last=0; 218 Update1(1,z+1,t); 219 printf("%d %d\n",first-1,last-1); 220 } 221 else 222 printf("Can not put any one.\n"); 223 } 224 else 225 { 226 num=0; 227 Update2(1,z+1,y+1); 228 printf("%d\n",num); 229 } 230 } 231 printf("\n"); 232 } 233 return 0; 234 }