/**//* 题意:给出一个序列,Q个询问,问[x,y]内数字之和(去掉重复数字) n <= 30000 Q <= 100000
一开始我想的是在线处理,怎么都构造不出
离线处理 对查询按照右端点排序,用last记录上一次插入的位置(这时a[1last]都插入过),同时用pre[x]记录值为x 的最后一个位置 (pre[]可用map实现,也可以离散化实现) 这样,当遇到一个值x,之前还没插入的话就直接在该位置插入 否则,先删除上一次插入的位置,再插入 这样子,只保留每个值的最后一个位置!!!! 最后答案就是 sum(x,y)
参考 http://hi.baidu.com/forverlin1204/blog/item/e1769a89d1789298a4c272e3.html */ #include<cstdio> #include<cstring> #include<algorithm> #include<map>
using namespace std;
const int MAXN = 30010; const int MAXM = 100010;
struct OP { int x, y ,id; bool operator < (const OP &B)const //一开始我按照左端点排序,是错误的,但是给我tle不知哪里写错 { return y < B.y; } };
OP op[MAXM]; long long C[MAXN] , ans[MAXM]; int a[MAXN] , n;
inline int lowbit(int x) { return x&(-x); }
long long Sum(int p) { long long ans = 0; while(p > 0) { ans += C[p]; p -= lowbit(p); } return ans; }
void insert(int p , int x) { while(p<=n) { C[p] += x; p += lowbit(p); } }
long long sum[MAXN*4];
void insert(int p ,int left , int right ,int pos ,int val) { if(pos < left || right < pos)return; sum[p] += val; if(left == right)return; int mid = (left+right)>>1; insert(2*p,left,mid,pos,val); insert(2*p+1,mid+1,right,pos,val); }
long long query(int p ,int left, int right , int l , int r) { if(l<=left && right <=r)return sum[p]; long long ans = 0; int mid = (left + right )>>1; if(l<=mid)ans+=query(2*p,left,mid,l,r);//注意都是l,r if(r>mid)ans+=query(2*p+1,mid+1,right,l,r); return ans; }
int main() { #ifdef ONLINE_JUDGE #else freopen("in","r",stdin); #endif
int T , Q; for(scanf("%d",&T); T--;) { scanf("%d",&n); for(int i = 1 ; i <= n ;i++) scanf("%d",&a[i]);
scanf("%d",&Q); for(int i = 0 ; i < Q ; i++) { scanf("%d%d",&op[i].x,&op[i].y); op[i].id = i; } sort(op,op+Q);
map<int,int> pre; for(int i = 1 ; i <= n; i++)C[i] = 0; //for(int i = 1 ; i <= 4*n ;i++) // sum[i] = 0; int last = 0; for(int i = 0; i < Q; i++) { for(int j = last + 1 ; j <= op[i].y ; j++)//这样子会铺满这个区间,所以是O(nlogn) { map<int,int>::iterator it = pre.find(a[j]); if(it != pre.end()) insert(it->second , -a[j]); //insert(1,1,n,it->second,-a[j]); pre[a[j]] = j; insert(j,a[j]); //insert(1,1,n,j,a[j]); } last = op[i].y; ans[op[i].id] = Sum(op[i].y) - Sum(op[i].x-1); //ans[op[i].id] = query(1,1,n,op[i].x,op[i].y); } for(int i = 0 ; i < Q; i++) printf("%I64d\n",ans[i]); } return 0; }
|