一、题目
二、分析
这题主要还是在区间的处理上。
为了保证区间内的数没有重复的,那么可以对区间按右端点从小到大排序,这样对原数组处理时,尽量保证不重复的元素靠右(可以假设右端点固定考虑),就可以保证区间求出来的值是不重复的,对于重复的就把前面位置出现的这个数减掉(即赋值为0)即可。
由于原数组的数比较大,要记录其之前的位置无法直接开数组,所以需要离散化。后面的就是普通的线段树的单点修改和区间查询了。
三、AC代码
#include <bits/stdc++.h> using namespace std; #define ll long long #define Min(a,b) ((a)>(b)?(b):(a)) #define Max(a,b) ((a)>(b)?(a):(b)) #define lson (rt<<1) #define rson (rt<<1|1) #define P pair<int, int> const int MAXN = 3e4; const int MAXQ = 1e5; ll A[MAXN + 13], Sum[MAXN<<2]; int Pre[MAXN + 13]; vector<ll> vec; struct node { int L, R, id; bool operator < (const node &t) const { return R < t.R; } }B[MAXQ + 13]; ll Ans[MAXQ + 13]; int getPos(ll x) { return lower_bound(vec.begin(), vec.end(), x) - vec.begin(); } void Push_up(int rt) { Sum[rt] = Sum[lson] + Sum[rson]; return; } void Update(int rt, int l, int r, int p, ll val) { if(l == r) { Sum[rt] = val; return; } int mid = (l + r) >> 1; if(p <= mid) Update(lson, l, mid, p, val); else Update(rson, mid + 1, r, p, val); Push_up(rt); } ll Query(int rt, int l, int r, int L, int R) { if(L <= l && r <= R) { return Sum[rt]; } int mid = (l + r) >> 1; ll ans = 0; if(L <= mid) ans += Query(lson, l, mid, L, R); if(R > mid) ans += Query(rson, mid + 1, r, L, R); return ans; } int main() { //freopen("input.txt", "r", stdin); // freopen("out.txt", "w", stdout); int T; scanf("%d", &T); while(T--) { int N, Q; scanf("%d", &N); vec.clear(); for(int i = 1; i <= N; i++) { scanf("%lld", &A[i]); vec.push_back(A[i]); } sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end()); scanf("%d", &Q); for(int i = 0; i < Q; i++) { scanf("%d%d", &B[i].L, &B[i].R); B[i].id = i; } sort(B, B + Q); memset(Sum, 0, sizeof(Sum)); memset(Pre, -1, sizeof(Pre)); //某个数字之前出现的位置 for(int i = 1, j = 0; i <= N; i++) { int p = getPos(A[i]); if(Pre[p] != -1) { Update(1, 1, N, Pre[p], 0); } Pre[p] = i; Update(1, 1, N, i, A[i]); for(; j < Q; j++) { if(B[j].R != i) { break; } Ans[B[j].id] = Query(1, 1, N, B[j].L, B[j].R); } } for(int i = 0; i < Q; i++) { printf("%lld ", Ans[i]); } } return 0; }