poj 3667 线段树成端更新区间最大连续和

浪子不回头ぞ 提交于 2020-01-24 15:22:38

题目描述:

输入包括n,m,n表示现在一共有n个相邻的房间,m表示有m条命令。

1 a 表示现在来了一个人数为a的队伍,需要一个连续的区间能够容纳这么多人,如果能够容纳,输入最靠左边的房间的号码,否则输出0。

2 a,b  表示清空[a,a+b-1]区间内所有的房子

 

解题思路:

   线段树结构体,定义需要记录的三个值,最大左连续、最大右连续、最大连续。

由上面的图可知,我们现在要更新两端区间,此时,合并区间的最大连续房间数只有三种情况:

1、  左区间最大连续房间数

2、  右区间最大连续房间数

3、  左区间最大右连续房间数 + 右区间最大左连续房间数

只要能够维护这些值,当中的更新和询问就好办了。

代码:

View Code
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 using namespace std;
 5 const int N = 50005;
 6 int mmax[N<<2],lmax[N<<2],rmax[N<<2],cover[N<<2];
 7 void PushDown(int t,int m)
 8 {
 9      if(cover[t]!=-1)
10      {
11         cover[t<<1]=cover[t<<1|1]=cover[t];
12         mmax[t<<1]=lmax[t<<1]=rmax[t<<1]=cover[t]?0:m-(m>>1);
13         mmax[t<<1|1]=lmax[t<<1|1]=rmax[t<<1|1]=cover[t]?0:(m>>1);
14         cover[t]=-1;
15      }
16 }
17 void PushUp(int t,int m)
18 {
19      lmax[t]=lmax[t<<1];
20      if(lmax[t]==(m-(m>>1)))lmax[t]+=lmax[t<<1|1];
21      rmax[t]=rmax[t<<1|1];
22      if(rmax[t]==(m>>1))rmax[t]+=rmax[t<<1];
23      mmax[t]=max(mmax[t<<1],mmax[t<<1|1]);
24      mmax[t]=max(mmax[t],rmax[t<<1]+lmax[t<<1|1]);
25 }
26 void build(int t,int l,int r)
27 {
28      mmax[t]=lmax[t]=rmax[t]=r-l+1;
29      cover[t]=-1;
30      if(l==r) return ;
31      int m=(l+r)>>1;
32      build(t<<1,l,m);
33      build(t<<1|1,m+1,r);
34 }
35 int query(int t,int l,int r,int w)
36 {
37     if(l==r)return l;
38     PushDown(t,r-l+1);
39     int m=(l+r)>>1;
40     if(mmax[t<<1]>=w)return query(t<<1,l,m,w);
41     else
42       if(rmax[t<<1]+lmax[t<<1|1]>=w)return m-rmax[t<<1]+1;
43     return query(t<<1|1,m+1,r,w);
44 }
45 void update(int t,int l,int r,int L,int R,int val)
46 {
47     if(L<=l&&r<=R)
48     {
49        mmax[t]=lmax[t]=rmax[t]=val?0:r-l+1;
50        cover[t]=val;
51        return ;
52     }
53     PushDown(t,r-l+1);
54     int m=(l+r)>>1;
55     if(L<=m)update(t<<1,l,m,L,R,val);
56     if(R>m)update(t<<1|1,m+1,r,L,R,val);
57     PushUp(t,r-l+1);
58 }
59 int main()
60 {
61     int n,m,o,a,b;
62     while(scanf("%d%d",&n,&m)!=EOF)
63     {
64           build(1,1,n);
65           for(int i=0;i<m;i++)
66           {
67               scanf("%d",&o);
68               if(o==1)
69               {
70                  scanf("%d",&a);
71                  if(mmax[1]<a)printf("0\n");
72                  else
73                  {
74                       int pos=query(1,1,n,a);
75                       printf("%d\n",pos);
76                       update(1,1,n,pos,pos+a-1,1);
77                  }
78               }
79               else
80               {
81                  scanf("%d%d",&a,&b);
82                  update(1,1,n,a,a+b-1,0);
83               }   
84           }
85     }
86     return 0;    
87 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!