题意:求区间内不同的数的和
离线处理,按查询右端点从小到大排序,从左往右扫一遍。
记录每个数出现的上一个位置,如果该数之前没有出现过,就加上,否则就在上一个位置减去。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define LL long long int using namespace std; const int MAXN = 1000100; struct node { int id; int l, r; }; int N, Q; int pre[MAXN]; //某数之前出现的位置 LL sum[50100]; LL val[50100]; int maxL; node D[200100]; LL ans[200100]; int lowbit( int x ) { return x&(-x); } LL query( int x ) { LL res = 0; while ( x > 0 ) { res += sum[x]; x -= lowbit(x); } return res; } void update( int x, int val ) { while ( x <= N ) { sum[x] += val; x += lowbit(x); } return; } bool cmp( node a, node b ) { if ( a.r != b.r ) return a.r < b.r; else if ( a.l != b.r ) return a.l < b.l; return a.id < b.id; } int main() { int T; scanf( "%d", &T ); while ( T-- ) { scanf( "%d", &N ); for ( int i = 1; i <= N; ++i ) scanf( "%I64d", &val[i] ); scanf( "%d", &Q ); for ( int i = 0; i < Q; ++i ) { D[i].id = i; scanf( "%d%d", &D[i].l, &D[i].r ); } memset( pre, -1, sizeof(pre) ); memset( sum, 0, sizeof(sum) ); sort( D, D + Q, cmp ); int cur = 1; for ( int i = 0; i < Q; ++i ) { while ( cur <= D[i].r ) { if ( pre[ val[cur] ] != -1 ) update( pre[ val[cur] ], -val[cur] ); update( cur, val[cur] ); pre[ val[cur] ] = cur; ++cur; } ans[ D[i].id ] = query( D[i].r ) - query( D[i].l - 1 ); } for ( int i = 0; i < Q; ++i ) printf( "%I64d ", ans[i] ); } return 0; }