1. 程式人生 > >2018年6月4號(線段樹(4))

2018年6月4號(線段樹(4))

描述 content IV region 編號 枚舉 sticky har bsp

  今天想和大家一起了解下今天我剛寫的一道題:

  P1558 色板遊戲

  題目背景

  阿寶上學了,今天老師拿來了一塊很長的塗色板。

  題目描述

  色板長度為L,L是一個正整數,所以我們可以均勻地將它劃分成L塊1厘米長的小方格。並從左到右標記為1, 2, ... L。現在色板上只有一個顏色,老師告訴阿寶在色板上只能做兩件事:1. "C A B C" 指在A到 B 號方格中塗上顏色 C。2. "P A B" 指老師的提問:A到 B號方格中有幾種顏色。學校的顏料盒中一共有 T 種顏料。為簡便起見,我們把他們標記為 1, 2, ... T. 開始時色板上原有的顏色就為1號色。 面對如此復雜的問題,阿寶向你求助,你能幫助他嗎?

  輸入輸出格式

  輸入格式:

  第一行有3個整數 L (1 <= L <= 100000), T (1 <= T <= 30) 和 O (1 <= O <= 100000). 在這裏O表示事件數, 接下來 O 行, 每行以 "C A B C" 或 "P A B" 得形式表示所要做的事情(這裏 A, B, C 為整數, 可能A> B)

  輸出格式:

對於老師的提問,做出相應的回答。每行一個整數。

  輸入輸出樣例

  輸入樣例#1: 復制
  2 2 4
  C 1 1 2
  P 1 2
  C 2 2 2
  P 1 2
  輸出樣例#1: 復制
  2
  1
  這道題最主要的是處理顏色,首先我們可以想到暴力枚舉顏色,經過多年的經驗(其實就那麽幾天);
絕對會超時;
所以我去詢問了我們班大佬,打聽到一個好方法:用二進制代替有無用這種顏色;
eg:10101表示用了1和3和5編號顏色,沒有用其他;
有人會問如何將左子樹和右子樹合並,所以我們就必須用或(|);
有如下效果:
  100
|  001
---------
101
就進行合並了;
所以代碼就很好實現:
 1 #include<bits/stdc++.h>
 2 #define zhi 100001
 3 using namespace std;
 4 struct
node{ 5 int l,r,dis,vis; 6 }tree[zhi*4]; 7 int x,y,t; 8 void buid(int p,int l,int r) 9 { 10 tree[p].l=l; 11 tree[p].r=r; 12 tree[p].dis=1; 13 if(l==r) 14 return ; 15 buid(p*2,l,(l+r)/2); 16 buid(p*2+1,(l+r)/2+1,r); 17 } 18 int zhuang(int s) 19 { 20 int tot=0; 21 while(s!=0) 22 { 23 if(s%2) 24 tot++; 25 s/=2; 26 } 27 return tot; 28 } 29 void pdown(int p) 30 { 31 if(tree[p].vis) 32 { 33 tree[p*2].dis=tree[p].vis; 34 tree[p*2].vis=tree[p].vis; 35 tree[p*2+1].dis=tree[p].vis; 36 tree[p*2+1].vis=tree[p].vis; 37 tree[p].vis=0; 38 } 39 } 40 void xiugai(int p) 41 { 42 if(x<=tree[p].l&&y>=tree[p].r) 43 { 44 tree[p].dis=(1<<t); 45 tree[p].vis=tree[p].dis; 46 return ; 47 } 48 pdown(p); 49 int mid=(tree[p].l+tree[p].r)/2; 50 if(x<=mid) 51 xiugai(p*2); 52 if(y>mid) 53 xiugai(p*2+1); 54 tree[p].dis=tree[p*2].dis|tree[p*2+1].dis; 55 } 56 int ask(int p) 57 { 58 if(x<=tree[p].l&&y>=tree[p].r) 59 return tree[p].dis; 60 pdown(p); 61 int mid=(tree[p].l+tree[p].r)/2,a=0,b=0; 62 if(x<=mid) 63 a=ask(p*2); 64 if(y>mid) 65 b=ask(p*2+1); 66 return a|b; 67 } 68 int main() 69 { 70 char u; 71 int m,n,l,a,b; 72 cin>>n>>m>>l; 73 buid(1,1,n); 74 for(int i=1;i<=l;++i) 75 { 76 cin>>u; 77 cin>>a>>b; 78 x=min(a,b); 79 y=max(a,b); 80 if(u==C) 81 { 82 cin>>t; 83 t--; 84 xiugai(1); 85 } 86 else 87 printf("%d\n",zhuang(ask(1))); 88 } 89 return 0; 90 }

today is over!

2018年6月4號(線段樹(4))