程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 線段樹區間更新,區間統計 poj 2777 Count Color

線段樹區間更新,區間統計 poj 2777 Count Color

編輯:C++入門知識

線段樹區間更新,區間統計 poj 2777 Count Color


題意:

將一段長為L的板子染色,板子可分為編號為1,2,3...L的L段,總共有O次操作,操作有兩種:1.將A到B區間染為顏色C 2.詢問A到B區間有多少種顏色。顏色從1到T編號,不超過30種。

 

思路:1.由於顏色不超過30種,所以可以考慮位運算,每一位代表一種顏色,一個32位整數就可以存儲所有的顏色狀態。

2.對於操作一,就是區間更新操作,需要用lazy操作,當需要更新子節點時才往下更新,把子節點的顏色染為lazy的顏色(即上一個節點染得顏色),並且把lazy下移。(代碼中的pushdown函數),更新子節點後,用pushup函數將子節點的染色狀態更新到父節點。

3.對於操作二,就是區間詢問,也用到lazy操作,需要詢問子節點時使用pushdown函數將子節點染色,然後查詢到目標區間後,返回目標區間的染色狀態(一個32位整數),最後將所查區間的染色狀態按位與,二進制中1的個數即所用顏色的數目。

易錯點:

1.注意使用lazy操作,不然超時。

2.建樹的時候也要用pushup操作更新父節點

3.在pushup函數中,是把左右子節點的染色狀態按位或,而pushdown函數中,是直接將父節點的上次所染顏色更新到子節點。原因是pushup是將子區間並起來,而pushdown是區間染色。

4.查詢的時候也要使用pushdown,因為有可能所查子節點狀態未被更新。

5.A可能大於B

代碼:

 

#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

#define PB push_back
#define MP make_pair

#define REP(i,x,n) for(int i=x;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define FORD(i,h,l) for(int i=(h);i>=(l);--i)
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define OI(X) printf("%d",X);
#define RS(X) scanf("%s", (X))
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
#define Swap(a, b) (a ^= b, b ^= a, a ^= b)
#define Dpoint  strcut node{int x,y}
#define cmpd int cmp(const int &a,const int &b){return a>b;}

 /*#ifdef HOME
    freopen("in.txt","r",stdin);
    #endif*/
const int MOD = 1e9+7;
typedef vector VI;
typedef vector VS;
typedef vector VD;
typedef long long LL;
typedef pair PII;
//#define HOME

int Scan()
{
	int res = 0, ch, flag = 0;

	if((ch = getchar()) == '-')				//判斷正負
		flag = 1;

	else if(ch >= '0' && ch <= '9')			//得到完整的數
		res = ch - '0';
	while((ch = getchar()) >= '0' && ch <= '9' )
		res = res * 10 + ch - '0';

	return flag ? -res : res;
}
/*----------------PLEASE-----DO-----NOT-----HACK-----ME--------------------*/
long long int col[400000+10];
int num;
int lazy[400000+10];
int l,t,o;
void pushdown(int rt)
{
    if(lazy[rt])
    {
        lazy[rt<<1]=lazy[(rt<<1)+1]=lazy[rt];
        col[rt<<1]=lazy[rt];
        col[(rt<<1)+1]=lazy[rt];
        lazy[rt]=0;
    }
}
void pushup(int rt)
{
    col[rt]=col[rt<<1]|(col[(rt<<1)+1]);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        col[rt]=1;


        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,(rt<<1)+1);
    pushup(rt);
}
void update(int l,int r,int rt,int a,int b,int c)
{
    if(a<=l&&r<=b)
    {
        col[rt]=c;
        lazy[rt]=c;
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(a<=m)
        update(l,m,rt<<1,a,b,c);
    if(b>m)
        update(m+1,r,(rt<<1)+1,a,b,c);
    pushup(rt);

}
long long int query(int l,int r,int rt,int a,int b)
{
    if(a<=l&&r<=b)
    {

        return col[rt];
    }
    pushdown(rt);
    int m=(l+r)>>1;
    long long int ans=0;
    if(a<=m)
        ans=ans|query(l,m,rt<<1,a,b);
    if(b>m)
        ans=ans|query(m+1,r,(rt<<1)+1,a,b);
     return ans;

}



int main()
{
cin>>l>>t>>o;
MS0(col);
MS0(lazy);
num=0;
build(1,l,1);


for(int i=0;ib)
        {
            Swap(a,b);
        }
        update(1,l,1,a,b,1<<(co-1));
    }
    else
    if(c=='P')
    {
        RII(a,b);
        num=0;
        if(a>b)
            Swap(a,b);
        long long int ans=query(1,l,1,a,b);
        for(int j=0;j

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved