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 "ps: 本題也可以用樹狀陣列完成,**量較少,容易實現。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 }
(完)
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之間...