 /**//*
題意:給出一個序列,Q個詢問,問[x,y]內(nèi)數(shù)字之和(去掉重復(fù)數(shù)字)
n <= 30000 Q <= 100000

一開始我想的是在線處理,怎么都構(gòu)造不出

離線處理
對查詢按照右端點排序,用last記錄上一次插入的位置(這時a[1 last]都插入過),同時用pre[x]記錄值為x
的最后一個位置 (pre[]可用map實現(xiàn),也可以離散化實現(xiàn))
這樣,當(dāng)遇到一個值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++)//這樣子會鋪滿這個區(qū)間,所以是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;
}
|