輸入第一行兩個正整數N和Q分別表示節點個數和操做次數接下來N-1行,每行兩個正整數u,v(1≤u,v≤n)表示u到v
有一條有向邊接下來Q行,形如「opernum」oper爲「C」時表示這是一個標記操做,oper爲「Q」時表示這是一個詢
問操做對於每次詢問操做,1 ≤ N, Q ≤ 100000。
題目:這裏php
題意:node
輸出一個正整數,表示結果ios
明顯與兩個相同的數在數組中的位置有關係。數組
求出顏色數組的前綴(前面一個該顏色值的位置)或者後綴(後一個該顏色的位置,之後綴爲例),這裏能夠用樹狀數組解決,將給沒個詢問區間按照左範圍從小到大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 }