标签:style blog http java color os
2 6 1 2 3 4 3 5 3 1 2 3 5 2 6 6 1 1 1 2 3 5 3 1 1 2 4 3 5
3 7 14 1 3 6
解题:离线树状数组,为什么要把y坐标从小到大进行排序呢?因为树状数组的特性所致,右边的节点可能包含左边的节点的值,所以从左往右,不断去掉重复的数值更简便。
离线处理即先一次性把所有询问存储起来。最后一次性回复。用一个数组pre[i]记录元素d[i]距离i最近的一次出现的下标。pre[i] == -1即表示该元素d[i]目前是唯一的,不存在重复元素的。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <climits> 7 #include <vector> 8 #include <queue> 9 #include <cstdlib> 10 #include <string> 11 #include <set> 12 #define LL long long 13 #define INF 0x3f3f3f 14 using namespace std; 15 const int maxn = 210000; 16 struct query { 17 int x,y,id; 18 } q[maxn]; 19 LL tree[51000]; 20 int pre[51000],loc[1100000],n,m,d[51000]; 21 LL ans[maxn]; 22 bool cmp(const query &a,const query &b) { 23 return a.y < b.y; 24 } 25 int lowbit(int x) { 26 return x&(-x); 27 } 28 void update(int x,int val) { 29 for(; x <= n; x += lowbit(x)) { 30 tree[x] += val; 31 } 32 } 33 LL sum(int x) { 34 LL ans = 0; 35 for(; x; x -= lowbit(x)) 36 ans += tree[x]; 37 return ans; 38 } 39 int main() { 40 int t,i,j; 41 scanf("%d",&t); 42 while(t--) { 43 memset(loc,-1,sizeof(loc)); 44 memset(tree,0,sizeof(tree)); 45 scanf("%d",&n); 46 for(i = 1; i <= n; i++) { 47 scanf("%d",d+i); 48 pre[i] = loc[d[i]]; 49 loc[d[i]] = i; 50 update(i,d[i]); 51 } 52 scanf("%d",&m); 53 for(i = 1; i <= m; i++) { 54 scanf("%d %d",&q[i].x,&q[i].y); 55 q[i].id = i; 56 } 57 sort(q+1,q+m+1,cmp); 58 int y = 0; 59 for(i = 1; i <= m; i++) { 60 for(j = y+1; j <= q[i].y; j++) { 61 if(pre[j] != -1) update(pre[j],-d[j]); 62 } 63 y = q[i].y; 64 ans[q[i].id] = sum(q[i].y) - sum(q[i].x-1); 65 } 66 for(i = 1; i <= m; i++) { 67 printf("%I64d\n",ans[i]); 68 } 69 } 70 return 0; 71 }
xtu数据结构 D. Necklace,布布扣,bubuko.com
标签:style blog http java color os
原文地址:http://www.cnblogs.com/crackpotisback/p/3858616.html