zoukankan      html  css  js  c++  java
  • P2894 [USACO08FEB]Hotel G

    题意就是维护整个序列最长连续01的位置,要求位置最左边,就是线段树最大连续子段和的查询操作稍作修改,每次查询分类讨论,如果左儿子内已经有满足题意的长度,就往左儿子找,如果左右凑起来有的话,就从左右凑起来,再查询右儿子有没有满足题意的长度.

    #include<iostream>
    #include<cstdio>
    #define rep(i,j,k) for(register int i(j);i<=k;++i)
    #define drp(i,j,k) for(register int i(j);i>=k;--i)
    #define bug cout<<"~~~~~~~~~~~~~"<<'
    ';
    #define bugout(x) cout<<x<<endl;
    using std::cin;
    using std::cout;
    typedef long long lxl;
    template<typename T>
    inline T  max(T a, T b) {
    	return a > b ? a : b;
    }
    template<typename T>
    inline T  min(T a, T b) {
    	return a < b ? a : b;
    }
    
    inline char gt() {
    	static char buf[1 << 21], *p1 = buf, *p2 = buf;
    	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
    }
    template <typename T>
    inline void  read(T &x) {
    	register char ch = gt();
    	x = 0;
    	int w(0);
    	while(!(ch >= '0' && ch <= '9'))w |= ch == '-', ch = gt();
    	while(ch >= '0' && ch <= '9')x = x * 10 + (ch & 15), ch = gt();
    	w ? x = ~(x - 1) : x;
    }
    template <typename T>
    inline void out(T x, char cc) {
    	if(x < 0) x = -x, putchar('-');
    	char ch[20];
    	int num(0);
    	while(x || !num) ch[++num] = x % 10 + '0', x /= 10;
    	while(num) putchar(ch[num--]);
    	putchar(cc);
    }
    
    const int N = 5e4 + 79;
    struct SegmentTree {
    
    	int sum[N << 2], lmax[N << 2], rmax[N << 2];
    	int lc[N << 2], rc[N << 2], tag[N << 2];
    	int rt, cnt;
    
    	inline void pushdown(int p, int L, int R) {
    		if(tag[p] == -1) return ;
    
    		int mid((L + R >> 1));
    		if(tag[p] == 1) {
    
    			sum[lc[p]] = lmax[lc[p]] = rmax[lc[p]] = mid - L + 1;
    			sum[rc[p]] = lmax[rc[p]] = rmax[rc[p]] = R - mid;
    		} else {
    			sum[lc[p]] = lmax[lc[p]] = rmax[lc[p]] = 0;
    			sum[rc[p]] = lmax[rc[p]] = rmax[rc[p]] = 0;
    		}
    
    		tag[lc[p]] = tag[rc[p]] = tag[p];
    		tag[p] = -1;
    	}
    
    	inline void pushup(int p, int L, int R) {
    
    		int mid(L + R >> 1);
    
    		if(sum[lc[p]] == mid - L + 1) {
    			lmax[p] = (mid - L + 1) + lmax[rc[p]];
    		} else {
    			lmax[p] = lmax[lc[p]];
    		}
    
    		if(sum[rc[p]] == R - mid) {
    			rmax[p] = (R - mid) + rmax[lc[p]];
    		} else {
    			rmax[p] = rmax[rc[p]];
    		}
    		sum[p] = max(max(sum[lc[p]], sum[rc[p]]), rmax[lc[p]] + lmax[rc[p]]);
    
    	}
    	inline void build(int &p, int L, int R) {
    		if(!p) p = ++cnt;
    		tag[p] = -1;
    		sum[p] = lmax[p] = rmax[p] = R - L + 1;
    		if(L == R) {
    			return ;
    		}
    		int mid(L + R >> 1);
    		build(lc[p], L, mid);
    		build(rc[p], mid + 1, R);
    	}
    	inline void change(int p, int L, int R, int ll, int rr, int val) {
    		if(ll <= L && rr >= R) {
    			if(val == 1) {
    				sum[p] = lmax[p] = rmax[p] = R - L + 1;
    				tag[p] = val;
    			} else {
    				sum[p] = lmax[p] = rmax[p] = 0;
    				tag[p] = val;
    			}
    			return;
    		}
    		pushdown(p, L, R);
    		int mid(L + R >> 1);
    		if(ll <= mid) change(lc[p], L, mid, ll, rr, val);
    		if(rr > mid) change(rc[p], mid + 1, R, ll, rr, val);
    		pushup(p, L, R);
    	}
    
    	inline int query(int p, int L, int R, int len) {
    		if(L == R) return L;
    		pushdown(p, L, R);
    		int mid(L + R >> 1);
    		if(sum[lc[p]] >= len) return query(lc[p], L, mid, len);
    		else if(rmax[lc[p]] + lmax[rc[p]] >= len) return mid - rmax[lc[p]] + 1; //左边的不够,加上右边够了
    		else if(sum[rc[p]] >= len) return query(rc[p], mid + 1, R, len);
    		return 0;
    	}
    } S; //空闲的当1,求区间最长连续子段和
    
    int n, m, k;
    
    int main() {
    //	freopen("hotel.in", "r", stdin);
    //	freopen("hotel.out", "w", stdout);
    	read(n);
    	read(m);
    
    	S.build(S.rt, 1, n);
    
    	int x, p;
    	while(m--) {
    		read(k);
    		if(k == 1) {
    			read(p);
    			if(S.sum[S.rt] < p) {
    				out(0, '
    ');
    			} else {
    				int po = S.query(S.rt, 1, n, p);
    				out(po, '
    ');
    				S.change(S.rt, 1, n, po, po + p - 1, 0);
    			}
    		} else {
    			read(x);
    			read(p);
    			S.change(S.rt, 1, n, x, x + p - 1, 1);
    		}
    	}
    	return 0;
    }
    

    本文来自博客园,作者:{2519},转载请注明原文链接:https://www.cnblogs.com/QQ2519/p/15375298.html

  • 相关阅读:
    SQL Server 2005高可用性之镜像功能
    Linux的常见问题解答和管理技巧
    安装sharepoint server 2007步骤
    CISCO 中对OSI的解释
    CISCO 2600 密码恢复
    三层交换机与路由器的比较
    PHP的注释
    php的变量、常量和数据类型
    操作符与控制结构
    【1】淘宝sdk装修入门引言
  • 原文地址:https://www.cnblogs.com/QQ2519/p/15375298.html
Copyright © 2011-2022 走看看