1. 程式人生 > >hdu-3333 Turing Tree 離線區間+樹狀數組(區間不同數的和)

hdu-3333 Turing Tree 離線區間+樹狀數組(區間不同數的和)

owb lld struct sync link urn pan cout space

題目鏈接:

http://acm.hdu.edu.cn/showproblem.php?pid=3333

題目大意:

給出一數組,以及m個查詢區間,每次查詢該區間不同數字的和。相同數字只加一次。

解題思路:

離線區間,按照區間右端點進行排序。

這樣可以從左到右掃一遍,用尺取法一個一個將數字放入樹狀數組中。

如果這個數字已經在樹狀數組裏面,記錄之前的下標,再從樹狀數組中刪去之前下標的這個數字,在當前下標添加該數字。這樣可以保證每一步操作,都會使得樹狀數組中沒有重復元素。這樣可以直接用樹狀數組求不同數字的和。

求區間種類數也是這樣做。

 1 #include<bits/stdc++.h>
 2
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf 3 #define Max(a, b) ((a) > (b) ? (a) : (b)) 4 #define Min(a, b) ((a) < (b) ? (a) : (b)) 5 #define Mem(a) memset(a, 0, sizeof(a)) 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1)) 7 #pragma comment(linker, "/STACK:102400000,102400000")//
棧外掛 8 using namespace std; 9 inline int read() 10 { 11 int x=0,f=1;char ch=getchar(); 12 while (ch<0||ch>9){if (ch==-) f=-1;ch=getchar();} 13 while (ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} 14 return x*f; 15 } 16 17 typedef long long ll; 18 const int maxn = 100000
+ 10; 19 const int MOD = 1000000007;//const引用更快,宏定義也更快 20 ll a[maxn];//樹狀數組 21 ll c[maxn];//原數組 22 map<ll, int>Last;//記錄上一次出現該值的下標 23 int n; 24 int lowbit(int x) 25 { 26 return x & (-x); 27 } 28 //向後修改某一點的值 29 void add(int x, ll d) 30 { 31 //cout<<x<<" "<<d<<endl; 32 while(x <= n) 33 { 34 a[x] += d; 35 x += lowbit(x); 36 } 37 } 38 //向前統計[1, x]的區間和 39 ll sum(int x) 40 { 41 ll ret = 0; 42 while(x > 0) 43 { 44 ret += a[x]; 45 x -= lowbit(x); 46 } 47 return ret; 48 } 49 struct node 50 { 51 int l, r; 52 int id; 53 node(){} 54 bool operator < (const node& a)const 55 { 56 return r < a.r; 57 } 58 }cnt[maxn];//離線區間 59 ll ans[maxn]; 60 int main() 61 { 62 int T, cases = 0; 63 scanf("%d", &T); 64 while(T--) 65 { 66 Last.clear(); 67 Mem(a); 68 int m; 69 scanf("%d", &n); 70 for(int i = 1; i <= n; i++)scanf("%lld", &c[i]); 71 scanf("%d", &m); 72 for(int i = 1; i <= m; i++)scanf("%d%d", &cnt[i].l, &cnt[i].r), cnt[i].id = i; 73 sort(cnt + 1, cnt + 1 + m); 74 int pre = 1; 75 for(int i = 1; i <= m; i++) 76 { 77 for(int j = pre; j <= cnt[i].r; j++) 78 { 79 if(Last[c[j]])//之前出現過 80 { 81 add(Last[c[j]], -c[j]); 82 } 83 add(j, c[j]); 84 Last[c[j]] = j; 85 } 86 pre = cnt[i].r + 1; 87 ans[cnt[i].id] = sum(cnt[i].r) - sum(cnt[i].l - 1); 88 } 89 for(int i = 1; i <= m; i++)printf("%lld\n", ans[i]); 90 } 91 return 0; 92 }

hdu-3333 Turing Tree 離線區間+樹狀數組(區間不同數的和)