HDU 3874 Necklace 树状数组

来源:互联网 发布:数据统计报表 编辑:程序博客网 时间:2024/05/19 20:57




Necklace

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1217    Accepted Submission(s): 462


Problem Description
Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count it once. We define the beautiful value of some interval [x,y] as F(x,y). F(x,y) is calculated as the sum of the beautiful value from the xth ball to the yth ball and the same value is ONLY COUNTED ONCE. For example, if the necklace is 1 1 1 2 3 1, we have F(1,3)=1, F(2,4)=3, F(2,6)=6.

Now Mery thinks the necklace is too long. She plans to take some continuous part of the necklace to build a new one. She wants to know each of the beautiful value of M continuous parts of the necklace. She will give you M intervals [L,R] (1<=L<=R<=N) and you must tell her F(L,R) of them.
 

Input
The first line is T(T<=10), representing the number of test cases.
  For each case, the first line is a number N,1 <=N <=50000, indicating the number of the magic balls. The second line contains N non-negative integer numbers not greater 1000000, representing the beautiful value of the N balls. The third line has a number M, 1 <=M <=200000, meaning the nunber of the queries. Each of the next M lines contains L and R, the query.
 

Output
For each query, output a line contains an integer number, representing the result of the query.
 

Sample Input
261 2 3 4 3 531 23 52 661 1 1 2 3 531 12 43 5
 

Sample Output
3714136
 


离线做会好做写,按结束坐标排序,然后扫一遍,遇到重复的,就把之前插入线段树的给删掉。这样的话,删掉前面的不会影响后面的结果。

用树状数组快很多。

线段树的:

#include <set>#include <map>#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string>#include <string.h>#include <algorithm>#define MID(x,y) ( ( x + y ) >> 1 )#define L(x) ( x << 1 )#define R(x) ( x << 1 | 1 )#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define file_r(x) freopen(x, "r", stdin)#define file_w(x) freopen(x, "w", stdout)using namespace std;const int MAX = 50010;const int MMAX = 1000010;typedef __int64 ll;int pre[MMAX];struct NODE{int x, y, id;void get(){scanf("%d%d", &x, &y);}};NODE a[MAX*4];int num[MAX];ll ans[MAX*4];struct Tnode{     int l,r;  ll sum;    int len() { return r - l;}    int mid() { return MID(l,r);}    bool in(int ll,int rr) { return l >= ll && r <= rr; }    void lr(int ll,int rr){ l = ll; r = rr;}};Tnode node[MAX<<2];void Updata_sum(int t){node[t].sum = node[L(t)].sum + node[R(t)].sum;}void Build(int t,int l,int r){node[t].lr(l,r);node[t].sum = 0;if( node[t].len() == 1 )return ;int mid = MID(l,r);Build(L(t),l,mid);Build(R(t),mid,r);}void Updata(int t,int l,int r,int val){if( node[t].in(l,r) ){node[t].sum = val;return ;}if( node[t].len() == 1 ) return ;int mid = node[t].mid();if( l < mid ) Updata(L(t),l,r,val);if( r > mid ) Updata(R(t),l,r,val);Updata_sum(t);}ll Query(int t,int l,int r){if( node[t].in(l,r) )return node[t].sum;if( node[t].len() == 1 ) return 0;int mid = node[t].mid();ll ans = 0ll;if( l < mid ) ans += Query(L(t),l,r);if( r > mid ) ans += Query(R(t),l,r);return ans;}bool cmp_y(NODE a, NODE b){if( a.y == b.y )return a.x < b.x;return a.y < b.y;}void solve(int n, int m){sort(a, a+m, cmp_y);memset(pre, -1, sizeof(pre));int st = 1;Build(1, 0, n);FOR(i, 0, m){while( st <= a[i].y ){if( pre[num[st]] == -1 ){pre[num[st]] = st;Updata(1, st-1, st, num[st]);}else{int pos = pre[num[st]];Updata(1, pos-1, pos, 0);pre[num[st]] = st;Updata(1, st-1, st, num[st]);}st++;}ans[a[i].id] = Query(1, a[i].x-1, a[i].y);}FOR(i, 0, m)printf("%I64d\n", ans[i]);}int main(){int ncases, n, m;scanf("%d", &ncases);while( ncases-- ){scanf("%d", &n);FOR(i, 1, n+1)scanf("%d", &num[i]);scanf("%d", &m);FOR(i, 0, m){a[i].id = i;a[i].get();}solve(n, m);}return 0;}


树状数组的

#include <set>#include <map>#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string>#include <string.h>#include <algorithm>#define FOR(i,s,t) for(int i=(s); i<(t); i++)#define file_r(x) freopen(x, "r", stdin)#define file_w(x) freopen(x, "w", stdout)using namespace std;const int MAX = 50010;const int MMAX = 1000010;typedef long long ll;int pre[MMAX];struct NODE{int x, y, id;void get(){scanf("%d%d", &x, &y);}};NODE a[MAX*4];int num[MAX];ll c[MAX], ans[MAX*4]; int lowbit(int x){return x & (-x);}void Updata(int x,int num)// num 可能都为1,具体问题具体分析 {int i;for(i=x; i<MAX; i+=lowbit(i))c[i] += num;// 若num 为1,c[i]++ }ll Getsum(int x)//sum的返回值的类型可能是long long ,根据题意判断 {ll sum = 0;for(int i=x; i>0; i-=lowbit(i))sum += c[i];return sum;}bool cmp_y(NODE a, NODE b){if( a.y == b.y )return a.x < b.x;return a.y < b.y;}void solve(int n, int m){sort(a, a+m, cmp_y);memset(pre, -1, sizeof(pre));memset(c, 0, sizeof(c));int st = 1;FOR(i, 0, m){while( st <= a[i].y ){if( pre[num[st]] == -1 ){pre[num[st]] = st;Updata(st, num[st]);}else{int pos = pre[num[st]];Updata(pos, -num[st]);pre[num[st]] = st;Updata(st, num[st]);}st++;}ans[a[i].id] = Getsum(a[i].y);if( a[i].x != 1 )ans[a[i].id] -= Getsum(a[i].x-1);}FOR(i, 0, m)printf("%I64d\n", ans[i]);}int main(){int ncases, n, m;scanf("%d", &ncases);while( ncases-- ){scanf("%d", &n);FOR(i, 1, n+1)scanf("%d", &num[i]);scanf("%d", &m);FOR(i, 0, m){a[i].id = i;a[i].get();}solve(n, m);}return 0;}



原创粉丝点击