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 }
转载于:https://www.cnblogs.com/by-1075324834/p/4543002.html
kb-07线段树-12--二分查找区间边界相关推荐
- poj 2892---Tunnel Warfare(线段树单点更新、区间合并)
题目链接 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensiv ...
- 线段树动态开点区间加区间求和
线段树动态开点区间加区间求和 题目来源: 陕西师范大学第七届程序设计竞赛网络同步赛 H. 万恶的柯怡 思想: 保证叶子节点被完整的覆盖,需要开节点,就把左右儿子都开出来,其余和普通线段树一样. tip ...
- 二分查找定边界(详细解析)
二分查找定边界 学习二分查找的过程中发现经常因为边界定的不正确导致最终结果出错,写篇博客整理一下.以下所有数组都默认是按升序排列的.Leetcode上这篇Binary Search 101总结得非常好 ...
- HDU 6070 Dirt Ratio(线段树、二分)
http://acm.hdu.edu.cn/showproblem.php?pid=6070 题解 首先不难看出错误率是单调的,那么我们可以直接二分答案x,某个区间的错误率=区间数的种类cnt/区间长 ...
- BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)
题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...
- hdu1394线段树点修改,区间求和
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给一个0-n-1的排列,这个排列中的逆序数为数对 (ai, aj) 满足 i < j a ...
- 数据结构树之二分查找树
二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: ...
- CodeForces - 487B Strip(线段树+dp+二分)
题目链接:点击查看 题目大意:给出一个长度为 n 的序列,现在要求分成尽可能少的子段,且每个子段需要满足: 最大值与最小值的差值小于等于 s 子段长度大于等于 l 题目分析:dp[ i ] 代表的是前 ...
- HDU 3974 Assign the task(DFS序+线段树单点查询,区间修改)
描述 There is a company that has N employees(numbered from 1 to N),every employee in the company has a ...
最新文章
- Spring Boot中使用JavaMailSender发送邮件
- http2-stream-optima-prioritation
- 大数据是电网创新变革的重要驱动力
- MySQL-性能优化_影响MySQL性能的因素分析及解决方案
- Bug接口地址找不到
- 分布式系统概念 | 分布式锁:数据库、Redis、Zookeeper解决方案
- Spring Security中的SecurityContext和SecurityContextHolder是什么?
- python.day05
- Python数模笔记-PuLP库(1)线性规划入门
- 晶晶赴约会(信息学奥赛一本通-T1049)
- [图论]最短路计数(spfa)
- Python 语言 Hello world
- Java Web(一) Servlet详解!!
- oracle采购业务流程,ORACLE ERP订单到现金流程图解
- 专用发票扫描识别SDK
- 步进电机驱动技术3:基于ULN2003的步进电机驱动
- 抖音:运营与商业模式分析
- stata:第九章 时间序列数据回归:平稳变量
- 补丁冷启动模式_Bilibili 移动端组件化实践中的冷启动优化
- wordpress博客引用外链图片加载不出