zoukankan      html  css  js  c++  java
  • HDU 3911 Black And White 分段树 题解

    Problem Description
    There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she want to know the longest period of consecutive black stones in a range [i, j].
     

    Input
      There are multiple cases, the first line of each case is an integer n(1<= n <= 10^5), followed by n integer 1 or 0(1 indicates black stone and 0 indicates white stone), then is an integer M(1<=M<=10^5) followed by M operations formatted as x i j(x = 0 or 1) , x=1 means change the color of stones in range[i,j], and x=0 means ask the longest period of consecutive black stones in range[i,j]
     

    Output
    When x=0 output a number means the longest length of black stones in range [i,j].
     

    Sample Input
    4 1 0 1 0 5 0 1 4 1 2 3 0 1 4 1 3 3 0 4 4
     

    Sample Output
    1 2 0

    分段树依旧是难题,本题能够说是分段树的基本操作,可是由于情况好多,程序好长,所以十分耗时间。

    之所以使用线段树,不使用一般的动态规划法,是要把每次查询的时间效率降到 (Lgn)。

    分段,每段都要维护8个数据,所以非常繁琐。

    做的好累,代码改动了非常多次,终于代码算比較清晰的了。有分段树思想的人应该都不难follow。

    Hdu是不同意使用free释放空间的,否则出错,奇怪的OJ。

    #pragma once
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    
    class BlackAndWhite3911
    {
    	int arrSize, tSize;
    	int *arr;
    	struct Node
    	{
    		int le0, le1, ri0, ri1;
    		int len0, len1;
    		int totalLen;
    		bool lazy;
    	};
    
    	Node *SegTree;
    	void updateNode(int r, int L, int R)
    	{
    		if (SegTree[L].le0 == SegTree[L].totalLen)
    			SegTree[r].le0 = SegTree[L].le0 + SegTree[R].le0;
    		else	SegTree[r].le0 = SegTree[L].le0;
    
    		if (SegTree[R].ri0 == SegTree[R].totalLen)
    			SegTree[r].ri0 = SegTree[L].ri0 + SegTree[R].ri0;
    		else SegTree[r].ri0 = SegTree[R].ri0;
    
    		if (SegTree[L].le1 == SegTree[L].totalLen)
    			SegTree[r].le1 = SegTree[L].le1 + SegTree[R].le1;
    		else SegTree[r].le1 = SegTree[L].le1;
    
    		if (SegTree[R].ri1 == SegTree[R].totalLen)
    			SegTree[r].ri1 = SegTree[L].ri1 + SegTree[R].ri1;
    		else SegTree[r].ri1 = SegTree[R].ri1;
    
    		int a = max(SegTree[L].len0, SegTree[R].len0);
    		int b = SegTree[L].ri0 + SegTree[R].le0;
    		SegTree[r].len0 = max(a, b);
    
    		a = max(SegTree[L].len1, SegTree[R].len1);
    		b = SegTree[L].ri1 + SegTree[R].le1;
    		SegTree[r].len1 = max(a, b);		
    	}
    
    	void conHelper(int low, int up, int r = 0)
    	{
    		if (low == up)
    		{
    			if (0 == arr[low])
    			{
    				SegTree[r].len0 = 1, SegTree[r].len1 = 0;
    				SegTree[r].le0 = 1, SegTree[r].ri0 = 1;
    				SegTree[r].le1 = 0, SegTree[r].ri1 = 0;
    			}
    			else
    			{
    				SegTree[r].len0 = 0, SegTree[r].len1 = 1;
    				SegTree[r].le0 = 0, SegTree[r].ri0 = 0;
    				SegTree[r].le1 = 1, SegTree[r].ri1 = 1;
    			}
    			SegTree[r].lazy = false;
    			SegTree[r].totalLen = 1;
    			return ;
    		}
    
    		int mid = low + ((up-low)>>1);
    		int le = (r<<1) + 1;
    		int ri = (r<<1) + 2;
    
    		conHelper(low, mid, le);
    		conHelper(mid+1, up, ri);
    
    		SegTree[r].totalLen = up - low + 1;
    		updateNode(r, le, ri);
    		SegTree[r].lazy = false;
    	}
    
    	void conTree()
    	{
    		int h = (int) ceil(log((double)arrSize)/log(2.0)) + 1;
    		tSize = (int) pow(2.0, h) - 1;
    		SegTree = (Node *) malloc(sizeof(Node) * tSize);
    		conHelper(0, arrSize-1);
    	}
    
    	void accessNode(int r)
    	{
    		SegTree[r].lazy = !SegTree[r].lazy;
    		swap(SegTree[r].le0, SegTree[r].le1);
    		swap(SegTree[r].ri0, SegTree[r].ri1);
    		swap(SegTree[r].len0, SegTree[r].len1);
    	}
    
    	void segUpdate(const int low, const int up, int L, int R, int r = 0)
    	{
    		if (low == L && R == up)
    		{
    			accessNode(r);
    			return;
    		}
    
    		int le = (r<<1) + 1;
    		int ri = (r<<1) + 2;
    
    		if (SegTree[r].lazy)
    		{
    			SegTree[r].lazy = false;
    			if (le < tSize) accessNode(le);
    			if (ri < tSize) accessNode(ri);
    		}
    
    		int M = L + ((R-L)>>1);
    
    		if (up <= M) segUpdate(low, up, L, M, le);
    		else if (low > M) segUpdate(low, up, M+1, R, ri);
    		else
    		{
    			segUpdate(low, M, L, M, le);
    			segUpdate(M+1, up, M+1, R, ri);
    		}
    		updateNode(r, le, ri);
    	}
    
    	int getLongest(const int low, const int up, int L, int R, int r = 0)
    	{
    		if (low == L && R == up)//不能low <= L && R <= up
    		{
    			return SegTree[r].len1;
    		}
    
    		int le = (r<<1) + 1;
    		int ri = (r<<1) + 2;
    		if (SegTree[r].lazy) 
    		{
    			SegTree[r].lazy = false;
    			if (le < tSize) accessNode(le);
    			if (ri < tSize) accessNode(ri);
    		}
    
    		int M = L + ((R-L)>>1);
    
    		//在任一边子树
    		if (up <= M) return getLongest(low, up, L, M, le);
    		if (low > M) return getLongest(low, up, M+1, R, ri);
    
    		//跨左右子树的情况
    		int llen = getLongest(low, M, L, M, le);//(low, up, L, M, le);
    		int rlen = getLongest(M+1, up, M+1, R, ri);//(low, up, M+1, R, ri);
    
    		int a = min(M-low+1, SegTree[le].ri1);
    		int b = min(up-M, SegTree[ri].le1);
    		int c = a + b;
    
    		return max(c, max(llen, rlen));
    	}
    public:
    	BlackAndWhite3911()
    	{
    		int N;
    		while ( (scanf("%d", &N) != EOF))
    		{
    			arrSize = N;
    			arr = (int *)malloc(sizeof(int) * arrSize);
    
    			for (int i = 0; i < N; i++)
    			{
    				scanf("%d", &arr[i]);
    			}
    
    			conTree();
    
    			int T;
    			scanf("%d", &T);
    			int a, b, c;
    			while (T--)
    			{
    				scanf("%d %d %d", &a, &b, &c);
    				if (0 == a)
    					printf("%d
    ",getLongest(b-1, c-1, 0, arrSize-1));
    				else segUpdate(b-1, c-1, 0, arrSize-1);	
    			}
    		}
    	}
    
    	~BlackAndWhite3911()
    	{
    		if (arr) free(arr);
    		if (SegTree) free(SegTree);
    	}
    };



  • 相关阅读:
    HBase读写数据的详细流程及ROOT表/META表介绍
    HBase的概述和安装部署
    Linux常用命令行补充——持续更新
    电信项目java补充类
    Kafka的接口回调 +自定义分区、拦截器
    Kafka命令行操作及常用API
    Kafka概述及安装部署
    Kafka生产者案例报警告SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    python threading
    python thread
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3924102.html
Copyright © 2011-2022 走看看