1. 程式人生 > >【樹狀數組+離線查詢】HDU 3333 Turing Tree

【樹狀數組+離線查詢】HDU 3333 Turing Tree

scan 題意 can size esp ret close 位置 ons

https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/H

【題意】

給定一個數組,查詢任意區間內不同數字之和。

(n<=30000,Q<=100000,每個數字<=1 000 000 000)

【思路】

要算任意區間內不同數字之和,如果我們從左到右依次處理,每次只保留最右邊出現的數字,處理以當前數字為右端點的查詢,就能做到“不同數字之和”,即不重不漏。因此我們要離線處理查詢,按記錄每個數作為右端點的所有查詢區間。這裏要用到vector記錄固定右端點後每個所有查詢區間的左端點和查詢ID,要用map或unorderd_map記錄每個數之前出現的位置(要把那個位置的刪掉)

【Accepted】

技術分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<vector>
 8 #include<map>
 9 #include<unordered_map>
10 using namespace std;
11 const int maxn=1e5+3
; 12 typedef long long ll; 13 int n,m; 14 vector<pair<int,int> > p[maxn]; 15 map<ll,int> pre; 16 17 ll tree[maxn]; 18 ll a[maxn]; 19 ll ans[maxn]; 20 void init() 21 { 22 memset(ans,0,sizeof(ans)); 23 for(int i=1;i<=n;i++) 24 { 25 tree[i]=0LL; 26 } 27 pre.clear();
28 } 29 int lowbit(int x) 30 { 31 return x&(-x); 32 } 33 void add(int k,ll x) 34 { 35 while(k<=n) 36 { 37 tree[k]+=x; 38 k+=lowbit(k); 39 } 40 } 41 42 ll query(int k) 43 { 44 ll res=0LL; 45 while(k) 46 { 47 res+=tree[k]; 48 k-=lowbit(k); 49 } 50 return res; 51 } 52 ll query(int l,int r) 53 { 54 return query(r)-query(l-1); 55 } 56 int main() 57 { 58 int T; 59 scanf("%d",&T); 60 while(T--) 61 { 62 scanf("%d",&n); 63 init(); 64 for(int i=1;i<=n;i++) 65 { 66 cin>>a[i]; 67 p[i].clear(); 68 } 69 scanf("%d",&m); 70 int u,v; 71 for(int i=1;i<=m;i++) 72 { 73 scanf("%d%d",&u,&v); 74 p[v].push_back(make_pair(u,i)); 75 } 76 for(int i=1;i<=n;i++) 77 { 78 if(pre.count(a[i])) 79 { 80 add(pre[a[i]],-a[i]); 81 } 82 pre[a[i]]=i; 83 add(i,a[i]); 84 int sz=p[i].size(); 85 for(int k=0;k<sz;k++) 86 { 87 ans[p[i][k].second]=query(p[i][k].first,i); 88 } 89 } 90 for(int i=1;i<=m;i++) 91 { 92 cout<<ans[i]<<endl; 93 } 94 } 95 return 0; 96 }
View Code



【樹狀數組+離線查詢】HDU 3333 Turing Tree