標籤:strong lowbit \n 一個 class define bool 元素 引用
題目連結:
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 node50 {51 int l, r;52 int id;53 node(){}54 bool operator < (const node& a)const55 {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 離線區間+樹狀數組(區間不同數的和)