poj 3667 最长空白段+查询最左连续段

Hotel


大体分析:

   题意:从最左找连续空间,是否能找到。
   解法:同poj1823。
   //是1823的加强版,但是提交记录也是呵呵了。
   //多的一个操作就是查询操作了。

具体分析

  更新操作同poj1823
  查询操作:
           1. 先判断是都存在
           2. 如果存在,左儿子中有就递归找左儿子
           3. 如果左儿子的有连续+有儿子的左连续空间有,那就返回位置
           4. 否则,递归寻找右儿子
  //线段树真是奇妙,很多更新、查询操作都很巧妙

参考代码

 
 
  1. #include<iostream> 
  2. #include<cstring> 
  3. #include <algorithm> 
  4. #include<cstdlib> 
  5. #include<vector> 
  6. #include<cmath> 
  7. #include<stdlib.h> 
  8. #include<iomanip> 
  9. #include<list> 
  10. #include<deque> 
  11. #include<map> 
  12. #include <stdio.h> 
  13. #include <queue> 
  14.  
  15. #define maxn 201000+5 
  16.  
  17. #define inf 0x3f3f3f3f 
  18.   #define INF 0x3FFFFFFFFFFFFFFFLL 
  19. #define rep(i,n) for(i=0;i<n;i++) 
  20.  #define reP(i,n) for(i=1;i<=n;i++) 
  21.  
  22. #define ull unsigned long long 
  23.  #define ll long long 
  24. #define LL(x) x<<1 
  25.  #define RR(x) x<<1|1 
  26.  
  27. #define cle(a) memset(a,0,sizeof(a)) 
  28.  
  29. using namespace std; 
  30. struct node{ 
  31.     int l,r,lsum,rsum,msum; 
  32.     int flag; 
  33.     int mid(){ 
  34.         return (l+r)>>1
  35.     } 
  36.     void init(){ 
  37.         lsum=rsum=msum=(r-l+1)*flag; 
  38.     } 
  39. }tree[maxn*4]; 
  40. void build(int rt,int l,int r){ 
  41.     tree[rt].l=l,tree[rt].r=r,tree[rt].flag=1
  42.     tree[rt].init(); 
  43.     if(l==r)return
  44.     int mid=tree[rt].mid(); 
  45.     build(LL(rt),l,mid),build(RR(rt),mid+1,r); 
  46. void update(int rt,int l,int r,int flag){ 
  47.     if(l<=tree[rt].l&&r>=tree[rt].r){ 
  48.         tree[rt].flag=flag;tree[rt].init();return
  49.     } 
  50.     if(tree[rt].flag!=-1){ 
  51.         tree[LL(rt)].flag=tree[RR(rt)].flag=tree[rt].flag; 
  52.         tree[LL(rt)].init();tree[RR(rt)].init();tree[rt].flag=-1
  53.     } 
  54.     int mid=tree[rt].mid(); 
  55.     if(r<=mid)update(LL(rt),l,r,flag); 
  56.     else if(l>mid)update(RR(rt),l,r,flag); 
  57.     else { 
  58.         update(LL(rt),l,mid,flag);update(RR(rt),mid+1,r,flag); 
  59.     } 
  60.     if(tree[LL(rt)].lsum==tree[LL(rt)].r-tree[LL(rt)].l+1)tree[rt].lsum=tree[LL(rt)].lsum+tree[RR(rt)].lsum;  
  61.     else tree[rt].lsum=tree[LL(rt)].lsum;  
  62.     if(tree[RR(rt)].rsum==tree[RR(rt)].r-tree[RR(rt)].l+1)tree[rt].rsum=tree[LL(rt)].rsum+tree[RR(rt)].rsum;  
  63.     else tree[rt].rsum=tree[RR(rt)].rsum;  
  64.     tree[rt].msum=max(max(tree[LL(rt)].msum,tree[RR(rt)].msum),tree[LL(rt)].rsum+tree[RR(rt)].lsum);  
  65. int query(int rt,int l,int r,int w) 
  66.     if(l==r)return l; 
  67.     if(tree[rt].flag!=-1){ 
  68.         tree[LL(rt)].flag=tree[RR(rt)].flag=tree[rt].flag; 
  69.         tree[LL(rt)].init();tree[RR(rt)].init();tree[rt].flag=-1
  70.     } 
  71.     int mid=tree[rt].mid(); 
  72.     if(tree[LL(rt)].msum>=w) return query(LL(rt),l,mid,w); 
  73.     else if(tree[LL(rt)].rsum+tree[RR(rt)].lsum>=w)return mid-tree[LL(rt)].rsum+1
  74.     else return query(RR(rt),mid+1,r,w); 
  75. int main() 
  76. #ifndef ONLINE_JUDGE 
  77.      freopen("in.txt","r",stdin); 
  78.      //freopen("out.txt","w",stdout); 
  79. #endif 
  80.     int n,m; 
  81.     while(scanf("%d%d",&n,&m)!=EOF) 
  82.     { 
  83.         build(1,1,n); 
  84.         int i; 
  85.         rep(i,m){ 
  86.             int temp,x,y; 
  87.             scanf("%d",&temp); 
  88.             if(temp==1){ 
  89.                 scanf("%d",&x); 
  90.                 if(tree[1].msum<x)printf("%d\n",0); 
  91.                 else { 
  92.                     int be=query(1,1,n,x); 
  93.                     printf("%d\n",be); 
  94.                     update(1,be,be+x-1,0); 
  95.                 } 
  96.             } 
  97.             else
  98.                 scanf("%d%d",&x,&y); 
  99.                 update(1,x,x+y-1,1); 
  100.             } 
  101.         } 
  102.     } 
  103.     return 0
  104. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值