求一个序列中全部数字的和,当中数值同样的仅仅能计算一次。
先储存全部的请求,然后依照它们的右边界排序,在查询的同一时候更新区间。这里事实上有一点点DP的味道,在它进行某个查询之前,保证全部的反复数字(除去最后一个)都被删除光了,而且有不能影响其它查询,所以呢,仅仅能从近期的那个操作进行计算。1次query就可以
#include<iostream> #include<stdio.h> #include<string> #include<string.h> #include<algorithm> #include<vector> using namespace std; const int maxn = 50050; const int maxm = 200050; vector<int> vec; __int64 res[maxm]; __int64 ans; int pre[1000050]; void init() { vec.clear(); vec.push_back(0); memset(pre, 0, sizeof(pre)); } struct line{ int left, right, id; bool operator<(const line &y)const { return right < y.right; } }q[maxm]; struct node{ int left, right; __int64 sum; int mid(){ return (left+right)/2; } }tree[maxn*4]; void buildTree(int left, int right, int rt) { tree[rt].left = left; tree[rt].right = right; if(left == right){ int a; scanf("%d", &a); vec.push_back(a); return ; } int mid = tree[rt].mid(); buildTree(left, mid, rt<<1); buildTree(mid+1, right, rt<<1|1); tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; } void update(int left, int right, int rt, int pos, int add) { if(left == right){ tree[rt].sum = add; return ; } int mid = tree[rt].mid(); if(pos <= mid) update(left, mid, rt<<1, pos, add); if(pos > mid) update(mid+1, right, rt<<1|1, pos, add); tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; } void query(int left, int right, int rt, int L, int R) { if(L <= left && R >= right){ ans += tree[rt].sum; return ; } int mid = tree[rt].mid(); if(L <= mid) query(left, mid, rt<<1, L, R); if(R > mid) query(mid+1, right, rt<<1|1, L, R); } int main() { int T, M, N; scanf("%d", &T); while(T --) { scanf("%d", &N); init(); buildTree(1, N, 1); scanf("%d", &M); for(int i = 1; i <= M; i ++) { scanf("%d%d", &q[i].left, &q[i].right); q[i].id = i; } sort(q+1, q+M+1);//排序是从index=1開始的M个数 int qn = 0; for(int i = 1; i <= N && qn <=M; i ++) { if(pre[vec[i]] != 0){ update(1, N, 1, pre[vec[i]], 0); } update(1, N, 1, i, vec[i]); while(qn <= M && q[qn].right <= i){ ans = 0; if(q[qn].right == i){ query(1, N, 1, q[qn].left, q[qn].right); res[q[qn].id] = ans; } qn ++; } pre[vec[i]] = i; } for(int i = 1; i <= M; i ++) printf("%I64d ", res[i]); } return 0; }