zoukankan      html  css  js  c++  java
  • bzoj 1593: [Usaco2008 Feb]Hotel 旅馆【线段树】

    参考:https://blog.csdn.net/u010336344/article/details/53034372
    神一样的线段树
    线段树上维护:ll从左开始最长空段;rr从右开始最长空段;len区间中最长空段;tg:-1不全是空的,0区间内全是空的,1区间内全是满的;lz下传标记:-1没标记,1下传满的,0下传空的
    修改的时候,修改到一整个区间,就把lz和tg改了,ll、rr、len全改成r-l+1或者0
    然后下传标记的时候同上
    向上合并的时候,先把左右区间的ll、rr穿给当前区间,然后根据左右区间的tg是否为0(全空)来扩大当前区间的ll、rr;tg根据左右区间tg更改;len从左区间len、右区间len和左区间rl+右区间ll中取max
    查询的时候优先查左边即可,像二分一样在树上跳

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=100005;
    int n,m;
    struct xds
    {
    	int l,r,ll,rl,tg,len,lz;
    }t[N<<1];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void pd(int ro)
    {
    	if(t[ro].lz!=-1)
    	{
    		if(t[ro].lz==1)
    		{
    			t[ro<<1].rl=t[ro<<1].ll=t[ro<<1].len=0;
    			t[ro<<1|1].rl=t[ro<<1|1].ll=t[ro<<1|1].len=0;
    		}
    		else
    		{
    			t[ro<<1].rl=t[ro<<1].ll=t[ro<<1].len=t[ro<<1].r-t[ro<<1].l+1;
    			t[ro<<1|1].rl=t[ro<<1|1].ll=t[ro<<1|1].len=t[ro<<1|1].r-t[ro<<1|1].l+1;
    		}
    		t[ro<<1].tg=t[ro<<1|1].tg=t[ro].tg;
    		t[ro<<1].lz=t[ro<<1|1].lz=t[ro].lz;
    		t[ro].lz=-1;
    	}
    }
    void ud(int ro)
    {
    	if(t[ro<<1].tg==t[ro<<1|1].tg)
    		t[ro].tg=t[ro<<1].tg;
    	else
    		t[ro].tg=-1;
    	t[ro].ll=t[ro<<1].ll;
    	t[ro].rl=t[ro<<1|1].rl;
    	if(!t[ro<<1].tg)
    		t[ro].ll+=t[ro<<1|1].ll;
    	if(!t[ro<<1|1].tg)
    		t[ro].rl+=t[ro<<1].rl;
    	t[ro].len=max(max(t[ro<<1].len,t[ro<<1|1].len),t[ro<<1].rl+t[ro<<1|1].ll);
    }
    void build(int ro,int l,int r)
    {
    	t[ro].l=l,t[ro].r=r,t[ro].len=t[ro].ll=t[ro].rl=r-l+1,t[ro].lz=-1;
    	if(l==r)
    		return;
    	int mid=(l+r)>>1;
    	build(ro<<1,l,mid);
    	build(ro<<1|1,mid+1,r);
    }
    void update(int ro,int l,int r,int k)
    {
    	if(t[ro].l==l&&t[ro].r==r)
    	{
    		if(k)
    			t[ro].rl=t[ro].ll=t[ro].len=0;
    		else
    			t[ro].rl=t[ro].ll=t[ro].len=r-l+1;
    		t[ro].tg=t[ro].lz=k;
    		return;
    	}
    	pd(ro);
    	int mid=(t[ro].l+t[ro].r)>>1;
    	if(r<=mid)
    		update(ro<<1,l,r,k);
    	else if(l>mid)
    		update(ro<<1|1,l,r,k);
    	else
    		update(ro<<1,l,mid,k),update(ro<<1|1,mid+1,r,k);
    	ud(ro);
    }
    int ques(int ro,int k)
    {
    	int re=-1;
    	while(t[ro].l&&t[ro].len>=k)
    	{
    		if(t[ro].ll>=k)
    		{
    			re=t[ro].l;
    			break;
    		}
    		if(t[ro<<1].len>=k)
    			ro<<=1;
    		else
    		{
    			if(t[ro<<1].rl!=0&&t[ro<<1].rl+t[ro<<1|1].ll>=k)
    			{
    				re=t[ro<<1].r-t[ro<<1].rl+1;
    				break;
    			}
    			else
    				ro=ro<<1|1;
    		}
    	}
    	return re;
    }
    int main()
    {
    	n=read(),m=read();
    	build(1,1,n);
    	while(m--)
    	{
    		int o=read();
    		if(o==1)
    		{
    			int x=read(),now=ques(1,x);
    			if(now!=-1)
    			{
    				printf("%d
    ",now);
    				update(1,now,now+x-1,1);
    			}
    			else
    				puts("0");
    		}
    		else
    		{
    			int x=read(),y=read();
    			update(1,x,x+y-1,0);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    第八章 多线程编程
    Linked List Cycle II
    Swap Nodes in Pairs
    Container With Most Water
    Best Time to Buy and Sell Stock III
    Best Time to Buy and Sell Stock II
    Linked List Cycle
    4Sum
    3Sum
    Integer to Roman
  • 原文地址:https://www.cnblogs.com/lokiii/p/8992537.html
Copyright © 2011-2022 走看看