kb-07线段树-12--二分查找区间边界
2015-05-31 23:46
344 查看
/* hdu4614 本题刚开始想能不能记录该区间最前面开始的点,最后面的点,区间空的数量;但是病不行 然后线段树的本质是区间操作,所以!这题主要就是区间的空的全放满,只要定出区间的边界就好办了; 这里用二分查找的方法,现计算满足数量的区间的尾,因为头已经确定了,及时不放花也是确定的,只要靠数量定出尾就可以了; 然后就是区间修改了; */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAX_N 50001 using namespace std; int n,m,first,last,num,x; struct tree { int l,r,fir,las,s,same,val; }tr[MAX_N*4]; void build(int rt,int l,int r) { tr[rt].l=l;tr[rt].r=r; tr[rt].fir=l; tr[rt].las=r; tr[rt].s=0; tr[rt].val=r-l+1; if(l==r) { tr[rt].same=0; return ; } tr[rt].same=1; int mid=(l+r)/2; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void Pushup(int rt) { int l=rt<<1,r=rt<<1|1; if(tr[l].fir==0) tr[rt].fir=tr[r].fir; else tr[rt].fir=tr[l].fir; if(tr[r].las==0) tr[rt].las=tr[l].las; else tr[rt].las=tr[r].las; tr[rt].val=tr[r].val+tr[l].val; } void Pushdown(int rt) { if(tr[rt].l==tr[rt].r) return ; int l=rt<<1,r=rt<<1|1; if(tr[rt].same) { if(tr[rt].s==1) { tr[r].val=tr[l].val=0; tr[r].s=tr[l].s=1; tr[r].fir=tr[l].fir=0; tr[r].las=tr[l].las=0; tr[r].same=tr[l].same=1; tr[rt].same=0; } else { tr[r].val=tr[r].r-tr[r].l+1; tr[l].val=tr[l].r-tr[l].l+1; tr[r].s=tr[l].s=0; tr[r].same=tr[l].same=1; tr[r].fir=tr[r].l; tr[r].las=tr[r].r; tr[l].fir=tr[l].l; tr[l].las=tr[l].r; tr[rt].same=0; } } } void Update1(int rt,int l,int r) { if(x<=0) return ; if(tr[rt].val==0) return ;//在二分查找定区间后,少了这一句所以一直tle if(tr[rt].l==l&&tr[rt].val>0) { if(first==0) first=tr[rt].fir; if(tr[rt].val<=x) { if(last<tr[rt].las) last=tr[rt].las; x-=tr[rt].val; tr[rt].same=1; tr[rt].s=1; tr[rt].val=0; tr[rt].fir=0; tr[rt].las=0; return ; } } if(tr[rt].l==tr[rt].r) return ; Pushdown(rt); int L=rt<<1,R=rt<<1|1; if(l<=tr[L].r) { if(r<=tr[L].r) Update1(L,l,r); else Update1(L,l,tr[L].r); } if(r>=tr[R].l) { if(l>=tr[R].l) Update1(R,l,r); else Update1(R,tr[R].l,r); } Pushup(rt); } void Update2(int rt,int l,int r) { if(tr[rt].l==l&&tr[rt].r==r) { num+=r-l+1-tr[rt].val; tr[rt].val=r-l+1; tr[rt].s=0; tr[rt].same=1; tr[rt].fir=l; tr[rt].las=r; return; } if(tr[rt].l==tr[rt].r) return ; Pushdown(rt); int L=rt<<1,R=rt<<1|1; if(l<=tr[L].r) { if(r<=tr[L].r) Update2(L,l,r); else Update2(L,l,tr[L].r); } if(r>=tr[R].l) { if(l>=tr[R].l) Update2(R,l,r); else Update2(R,tr[R].l,r); } Pushup(rt); } int sum(int rt,int l,int r) { if(tr[rt].l==l&&tr[rt].r==r) { return tr[rt].val; } int ans=0; Pushdown(rt);//因为只是查询,所以区间整体并没有变,就没有必要pushup了; int L=rt<<1,R=rt<<1|1; if(l<=tr[L].r) { if(r<=tr[L].r) ans+= sum(L,l,r); else ans+= sum(L,l,tr[L].r); } if(r>=tr[R].l) { if(l>=tr[R].l) ans+= sum(R,l,r); else ans+= sum(R,tr[R].l,r); } return ans; } int bisearch(int a,int f) { if(sum(1,a,n)==0) return -1; if(sum(1,a,n)<f)//此处的等于号的问题; return n; int l=a,r=n; int ans=a; while(l<=r) { int mid=(l+r)/2; if(sum(1,a,mid)>=f)//以及此处的等于号; { ans=mid;//这里ans的取值; r=mid-1; } else l=mid+1; } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); build(1,1,n); for(int i=0;i<m;i++) { int ty,z,y; scanf("%d%d%d",&ty,&z,&y); if(ty==1) { int t=bisearch(z+1,y); if(t!=-1) { x=y; first=0; last=0; Update1(1,z+1,t); printf("%d %d\n",first-1,last-1); } else printf("Can not put any one.\n"); } else { num=0; Update2(1,z+1,y+1); printf("%d\n",num); } } printf("\n"); } return 0; }
相关文章推荐
- C++中调用开源库路径问题
- hdu 1022 Train Problem I (栈的应用)
- SRS文档
- 第一次接触MVC Models概念
- ubuntu配置JDK
- 导航条的设计与实现
- 深入理解java多线程中的join()
- 用文件的读写和string作为临时存储区复制图片文件
- 关于如何修改weblogic用户密码的问题
- php中一个完整表单处理实现代码
- SRS文档
- 数据库设计(2)_逻辑结构设计
- 如何编译openwrt
- 浅谈委托和事件(一)
- 浮动与定位
- HDU 2047
- Bitnami WordPress如何让默认URL指向WordPress目录?
- iOS - AFN - 错误码解决办法(-1016)
- 圆形链接
- Bitnami WordPress如何让默认URL指向WordPress目录?