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--二分查找区间边界相关推荐

  1. poj 2892---Tunnel Warfare(线段树单点更新、区间合并)

    题目链接 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensiv ...

  2. 线段树动态开点区间加区间求和

    线段树动态开点区间加区间求和 题目来源: 陕西师范大学第七届程序设计竞赛网络同步赛 H. 万恶的柯怡 思想: 保证叶子节点被完整的覆盖,需要开节点,就把左右儿子都开出来,其余和普通线段树一样. tip ...

  3. 二分查找定边界(详细解析)

    二分查找定边界 学习二分查找的过程中发现经常因为边界定的不正确导致最终结果出错,写篇博客整理一下.以下所有数组都默认是按升序排列的.Leetcode上这篇Binary Search 101总结得非常好 ...

  4. HDU 6070 Dirt Ratio(线段树、二分)

    http://acm.hdu.edu.cn/showproblem.php?pid=6070 题解 首先不难看出错误率是单调的,那么我们可以直接二分答案x,某个区间的错误率=区间数的种类cnt/区间长 ...

  5. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

  6. hdu1394线段树点修改,区间求和

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给一个0-n-1的排列,这个排列中的逆序数为数对 (ai, aj) 满足 i < j a ...

  7. 数据结构树之二分查找树

    二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: ...

  8. CodeForces - 487B Strip(线段树+dp+二分)

    题目链接:点击查看 题目大意:给出一个长度为 n 的序列,现在要求分成尽可能少的子段,且每个子段需要满足: 最大值与最小值的差值小于等于 s 子段长度大于等于 l 题目分析:dp[ i ] 代表的是前 ...

  9. 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 ...

最新文章

  1. Spring Boot中使用JavaMailSender发送邮件
  2. http2-stream-optima-prioritation
  3. 大数据是电网创新变革的重要驱动力
  4. MySQL-性能优化_影响MySQL性能的因素分析及解决方案
  5. Bug接口地址找不到
  6. 分布式系统概念 | 分布式锁:数据库、Redis、Zookeeper解决方案
  7. Spring Security中的SecurityContext和SecurityContextHolder是什么?
  8. python.day05
  9. Python数模笔记-PuLP库(1)线性规划入门
  10. 晶晶赴约会(信息学奥赛一本通-T1049)
  11. [图论]最短路计数(spfa)
  12. Python 语言 Hello world
  13. Java Web(一) Servlet详解!!
  14. oracle采购业务流程,ORACLE ERP订单到现金流程图解
  15. 专用发票扫描识别SDK
  16. 步进电机驱动技术3:基于ULN2003的步进电机驱动
  17. 抖音:运营与商业模式分析
  18. stata:第九章 时间序列数据回归:平稳变量
  19. 补丁冷启动模式_Bilibili 移动端组件化实践中的冷启动优化
  20. wordpress博客引用外链图片加载不出

热门文章

  1. form表单的两种提交方式,submit和button的用法
  2. python实现自顶向下,自底向上
  3. 八数码 poj 1077 广搜 A* IDA*
  4. git回退分支提交代码
  5. new和make的区别
  6. STM32的SPI驱动代码
  7. mybaits十五:使用trim自定义字符串的截取规则
  8. spring五:获取容器中对象信息
  9. 辨析Java与Javascript
  10. PHP:第一章——PHP中的关键字