【解題報告】VijosP1448校門外的樹(困難版)

原題:數組

校門外有不少樹,有蘋果樹,香蕉樹,有會扔石頭的,有能夠吃掉補充體力的……
現在學校決定在某個時刻在某一段種上一種樹,保證任一時刻不會出現兩段相同種類的樹,現有兩個操做:
K=1,K=1,讀入l、r表示在區間[l,r]中種上一種樹,每次操做種的樹的種類都不一樣
K=2,讀入l,r表示詢問l~r之間能見到多少種樹
(l,r>0)spa

輸入樣例:code

5 4
1 1 3
2 2 5
1 2 4
2 3 5blog

樣例輸出:排序

1
2博客

 

曾經,校門外的樹是幾行的暴力染色io

而後,校門外的樹是長長的線段樹class

後來啊,校門外的樹是幾行的樹狀數組效率

 

判斷詢問的區間與以前多少個已知區間有交集程序

若是將以前的已知區間雙關鍵字排序

再作二分查找

很快就能獲得有交集的區間數量

 

那麼如今只有兩個事情要辦:

一、排序,要讓已知的區間始終是有序的

二、查找,以logn的效率迅速找有交集的已知區間

能夠用來聯繫線段樹,也能做爲樹狀數組的嘗試

 

步驟(原來在寫線段樹的,寫到一半忽然發現樹狀數組可解,因而直接刪代碼寫樹狀數組):

1:若是當前根不爲空:獲得一個區間信息,從根開始,若是該區間比根小,則把左子節點當成根作下一次操做的根,比根大則把右子節點做爲下一次操做的根

2:若是當前根爲空:愉快地將該區間信息放在根位置上

3:返回第一步

 

個人程序:

 1 #include <stdio.h>
 2 int h[50010],t[50010];
 3 int n,k;
 4 void add(int a[],int k)
 5 {
 6     while(k<=n){
 7         a[k]++;
 8         k+=k&(-k);
 9     }
10 }
11 int search(int a[],int k)
12 {
13     int tot=0;
14     while(k){
15         tot+=a[k];
16         k-=k&(-k);
17     }
18     return tot;
19 }
20 int main()
21 {
22 
23     scanf("%d%d",&n,&k);
24     for(int i=1;i<=k;i++)
25     {
26         int a,b,c;
27         scanf("%d%d%d",&a,&b,&c);
28         if(a==1){
29             add(h,b);
30             add(t,c);
31         }
32         else printf("%d\n",search(h,c)-search(t,b-1));
33     }
34 }

PS:博客園第一文

相關文章
相關標籤/搜索