Vijos1448校門外的樹 題解

2022-06-02 16:27:11 字數 1936 閱讀 2185

vijos1448校門外的樹 題解

描述:

校門外有很多樹,有蘋果樹,香蕉樹,有會扔石頭的,有可以吃掉補充體力的……

k=1,k=1,讀入l、r表示在區間[l,r]中種上一種樹,每次操作種的樹的種類都不同

k=2,讀入l,r表示詢問l~r之間能見到多少種樹

(l,r>0)

輸入格式:

第一行n,m表示道路總長為n,共有m個操作

接下來m行為m個操作

輸出格式:

對於每個k=2輸出乙個答案

樣例輸入:

5 41 1 3

2 2 5

1 2 4

2 3 5

樣例輸出:12

資料範圍:

20%的資料保證,n,m<=100

60%的資料保證,n <=1000,m<=50000

100%的資料保證,n,m<=50000

~~~~~~~~~~~~~~~~~~~~~~~~~~~分割線~~~~~~~~~~~~~~~~~~~~~~~~~~~

分析:

這道題是乙個典型的區間問題,考慮到資料量較大,使用線段樹完成這個操作。由於樹的種類很多,不難想到用線段樹暴力維護的方法。但是暴力維護一定會超時,那麼這麼解決這個問題呢?

這裡介紹一種十分機智的想法——括號序列

假設有乙個長度為10的數軸,我們要將區間[ 2 , 5 ]中種樹,這時,我們將 2 處放乙個左括號 " ( "  ,5處放乙個 " )"  ,表示區間 [ 2 , 5 ]種了樹。

查詢某個區間樹的種類,如區間[ 3 , 10],只需統計10之前(包括10)有多少個『(』,統計3之前有多少個『)』,(不包括3)。  

如下圖所示:

以上就是括號序列的過程。簡單的說,就是更新區間[a,b]時,點a記錄左括號數,點b記錄右括號數,查詢區間[a,b]時,即為b之前(包括b)的左括號數-a之前的右括號數。

下面貼注釋**:

1 #include "

bits/stdc++.h"2

#define maxn 5001034

using

namespace

std ;

5 typedef long

long

qaq ;67

struct

tree8;

1213 tree tr[maxn << 2

];14

15void build_tree ( int x , int y , int i )//

建樹1627}

2829

void update_left ( int w , int

i )3039}

4041

void update_right ( int w , int i )//

同update_left

4251}52

53 qaq query_left ( int q , int w , int i )//

同query_right

5463}64

65 qaq query_right ( int q , int w , int

i )6675}

7677

intmain()

7890

else

9196}97

return0;

98 }

ps: 本題也可以用樹狀陣列完成,**量較少,容易實現。

(完)

Vijos 1448 校門外的樹 樹狀陣列

描述 校門外有很多樹,有蘋果樹,香蕉樹,有會扔石頭的,有可以吃掉補充體力的 如今學校決定在某個時刻在某一段種上一種樹,保證任一時刻不會出現兩段相同種類的樹,現有兩個操作 k 1,k 1,讀入l r表示在區間 l,r 中種上一種樹,每次操作種的樹的種類都不同 k 2,讀入l,r表示詢問l r之間能見到...

vijos1448 樹狀陣列 校門外的樹

傳送門biu 對於某一區間 l,r 來說,所有線段中左端點小於r的線段數的是 1,r 的答案,在這部分答案中,右端點在l左側的應該捨去,所以我們可以維護兩個樹狀陣列,乙個存左端點出現次數,乙個存右端點出現次數。include using namespace std int n,m,a 50001 b...

Vijos1448 校門外的樹 樹狀陣列

題目傳送門 校門外有很多樹,有蘋果樹,香蕉樹,有會扔石頭的,有可以吃掉補充體力的 如今學校決定在某個時刻在某一段種上一種樹,保證任一時刻不會出現兩段相同種類的樹,現有兩個操作 k 1,k 1,讀入l r表示在區間 l,r 中種上一種樹,每次操作種的樹的種類都不同 k 2,讀入l,r表示詢問l r之間...