Hotel
大体分析:
题意:最长的空白段,操作段的加入和删除操作
解法:线段树+lazy标记
具体操作:
> * 线段树维护,左边最长连续,右边最长连续、中间最长连续,因为之后边上的连续段对父亲的段才有影响
> * 添加Lazy标记才会保证时间~
> * 转移比较难理解
> * 符合poj 的一贯风格,空间一定要开的足够大(这样有意思嘛)
> * lazy标记的作用就是需要是有子树的时候才更新就好了。
代码c++
- #include<iostream>
- #include<cstring>
- #include <algorithm>
- #include<cstdlib>
- #include<vector>
- #include<cmath>
- #include<stdlib.h>
- #include<iomanip>
- #include<list>
- #include<deque>
- #include<map>
- #include <stdio.h>
- #include <queue>
- #define maxn 160000+5
- #define inf 0x3f3f3f3f
- #define INF 0x3FFFFFFFFFFFFFFFLL
- #define rep(i,n) for(i=0;i<n;i++)
- #define reP(i,n) for(i=1;i<=n;i++)
- #define ull unsigned long long
- #define ll long long
- #define LL(x) x<<1
- #define RR(x) x<<1|1
- #define cle(a) memset(a,0,sizeof(a))
- using namespace std;
- struct node{
- int l,r,lsum,msum,rsum;
- int flag;//1->全部可以入住 0->全部不可以入住
- int mid(){
- return (l+r)>>1;
- }
- void init(){
- lsum=msum=rsum=(r-l+1)*flag;
- }
- }tree[maxn*2];
- void build(int rt,int l,int r){
- tree[rt].l=l,tree[rt].r=r,tree[rt].flag=1,tree[rt].init();
- if(l==r)return;
- int mid=tree[rt].mid();
- build(LL(rt),l,mid),build(RR(rt),mid+1,r);
- }
- void update(int rt,int l,int r,int flag){
- if(l<=tree[rt].l&&r>=tree[rt].r){
- tree[rt].flag=flag;tree[rt].init();return;
- }
- if(tree[rt].flag!=-1)
- {
- tree[LL(rt)].flag=tree[RR(rt)].flag=tree[rt].flag;
- tree[rt].flag=-1;tree[LL(rt)].init();tree[RR(rt)].init();
- }
- int mid=tree[rt].mid();
- if(r<=mid)update(LL(rt),l,r,flag);
- else if(l>mid)update(RR(rt),l,r,flag);
- else {
- update(LL(rt),l,mid,flag),update(RR(rt),mid+1,r,flag);
- }
- 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;
- else tree[rt].lsum=tree[LL(rt)].lsum;
- 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;
- else tree[rt].rsum=tree[RR(rt)].rsum;
- tree[rt].msum=max(max(tree[LL(rt)].msum,tree[RR(rt)].msum),tree[LL(rt)].rsum+tree[RR(rt)].lsum);
- }
- int main()
- {
- #ifndef ONLINE_JUDGE
- freopen("in.txt","r",stdin);
- //freopen("out.txt","w",stdout);
- #endif
- int n,p;
- while(scanf("%d%d",&n,&p)!=EOF){
- int type,x,y;
- build(1,1,n);
- int i;
- rep(i,p){
- scanf("%d",&type);
- if(type==3){
- printf("%d\n",tree[1].msum);
- }
- else{
- scanf("%d%d",&x,&y);
- if(type==1)//入住
- {
- update(1,x,x+y-1,0);
- }
- else update(1,x,x+y-1,1);
- }
- }
- }
- return 0;
- }