HYSBZ 2743 (樹狀數組) 採花

題目:這裏php

題意:node

在2016年,佳媛姐姐剛剛學習了樹,很是開心。如今他想解決這樣一個問題:給定一顆有根樹(根爲1),有如下
兩種操做:1. 標記操做:對某個結點打上標記(在最開始,只有結點1有標記,其餘結點均無標記,並且對於某個
結點,能夠打屢次標記。)2. 詢問操做:詢問某個結點最近的一個打了標記的祖先(這個結點自己也算本身的祖
先)你能幫幫他嗎?

Input

輸入第一行兩個正整數N和Q分別表示節點個數和操做次數接下來N-1行,每行兩個正整數u,v(1≤u,v≤n)表示u到v
有一條有向邊接下來Q行,形如「opernum」oper爲「C」時表示這是一個標記操做,oper爲「Q」時表示這是一個詢
問操做對於每次詢問操做,1 ≤ N, Q ≤ 100000。

Output

輸出一個正整數,表示結果ios

Sample Input

5 5
1 2
1 3
2 4
2 5
Q 2
C 2
Q 2
Q 5
Q 3

Sample Output

1
2
2
1

HINT

 

明顯與兩個相同的數在數組中的位置有關係。數組

 

求出顏色數組的前綴(前面一個該顏色值的位置)或者後綴(後一個該顏色的位置,之後綴爲例),這裏能夠用樹狀數組解決,將給沒個詢問區間按照左範圍從小到大ide

排序,而後遍歷一邊大區間1到n,當 i 小於詢問範圍左端點的的時候將其加入樹狀數組,等於詢問範圍左端點的時候既求區間範圍和,注意的是,因爲只有同種學習

顏色的花的數目大於1纔算,因此事先將符合條件的花先加進數組,而後遍歷的時候考慮失去 i 這個位置的時候是加一仍是減一spa

 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int M = 1e6 + 10;
 8 int has[M],has1[M],vis[M],b[M],ans[M],n;
 9 int q[M];
10 
11 struct node{
12    int x,y,id;
13 }a[M];
14 
15 int lowbit(int x){return x&(-x);}
16 
17 void add(int x,int y)
18 {
19     while (x<=M){
20         has[x]+=y;
21         x+=lowbit(x);
22     }
23 }
24 
25 int getsum(int x)
26 {
27     int ans=0;
28     while (x>0){
29         ans+=has[x];
30         x-=lowbit(x);
31     }
32     return ans;
33 }
34 
35 bool cmp(node a,node b)
36 {
37     if (a.x==b.x) return a.y<b.y;
38     return a.x<b.x;
39 }
40 
41 int main()
42 {
43     int c,m;
44     bool flag=false;
45     scanf("%d%d%d",&n,&c,&m);
46     memset(vis,0,sizeof(vis));
47     memset(has1,0,sizeof(has1));
48     for (int i=1 ; i<=n ; i++){
49         scanf("%d",&b[i]);
50         /*if (has1[b[i]]==0) vis[i]=i,has1[b[i]]=i;
51         else{
52             vis[i]=has1[b[i]];
53             has1[b[i]]=i;
54         }*/
55     }
56     for(int i=n ;i>=1 ; i--){  //求後綴
57       vis[i]=has1[b[i]];
58       has1[b[i]]=i;
59    }
60     for (int i=1 ; i<=m ; i++){
61         scanf("%d%d",&a[i].x,&a[i].y);
62         a[i].id=i;
63     }
64     for(int i=1 ; i<=c ; i++){ //知足的先加上
65       if (vis[has1[i]])
66          add(vis[has1[i]],1);
67       //cout<<has1[i]<<endl;
68     }
69     sort(a+1,a+m+1,cmp);
70     int j=1;
71    // memset(q,0,sizeof(q));
72     for(int i=1 ; i<=m ; i++){
73       while (j<a[i].x){
74          if (vis[vis[j]])add(vis[vis[j]],1);
75          if (vis[j])  add(vis[j],-1);
76          j++;
77       }
78        ans[a[i].id]=getsum(a[i].y)-getsum(a[i].x-1);
79    }
80     for (int i=1 ; i<=m ; i++){
81         printf("%d\n",ans[i]);
82     }
83     //cout<<getsum(1)<<endl;
84     return 0;
85 }
View Code
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息