您的位置:首页 > 其它

HDU 3333&&HDU-3874 Necklace 离线树状数组

2014-06-24 09:49 375 查看
    这题是要求一段区间内的不重复的数字之和。我们通过对询问区间的右端点进行排序,然后记录每一数字的上一次的出现的位置,由于询问都是不回溯的那么就可以线性的更新了。

    

#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
int N,M;
int num[50050];
long long C[50050];
struct Node{
int L;
int R;
int id;
}P[200020];
long long ans[200020];
int lowbit(int x){
return x&(-x);
}
long long sum(int x){
long long ret=0;
while (x>0) {
ret+=C[x];x-=lowbit(x);
}
return ret;
}
int add(int x,long long d){
while (x<=N){
C[x]+=d;x+=lowbit(x);
}
return 0;
}
long long query(int L,int R){
return sum(R)-sum(L-1);
}
int cmp(Node a,Node b){
return a.R<b.R;
}
int main (){
int T;scanf("%d",&T);
while (T--){
map <int ,int > vis;
vis.clear();
scanf("%d",&N);
for (int i=0;i<N;i++)
scanf("%d",&num[i]),C[i]=0;
C
=0;
scanf("%d",&M);
for (int i=0;i<M;i++){
scanf("%d%d",&P[i].L,&P[i].R),P[i].id=i;
if (P[i].L>P[i].R){
int c=P[i].R;
P[i].R=P[i].L;
P[i].L=c;
}
}
sort(P,P+M,cmp);
int j=0;
for (int i=0;i<M;i++){
while (j<N&&j+1<=P[i].R){
if (vis[num[j]]!=0) {
add(vis[num[j]],-num[j]);
vis[num[j]]=j+1;
add(vis[num[j]],num[j]);
}
else {
vis[num[j]]=j+1;
add(vis[num[j]],num[j]);
}
j++;
}
ans[P[i].id]=query(P[i].L,P[i].R);
}
for (int i=0;i<M;i++){
printf("%I64d\n",ans[i]);
}
}
return 0;
}
就这道题卡了我三次T_T 读题必须要认真啊

这道题的区间可能是反的,可能给出的区间前面大后面小,需要判断一下。

写树状数组时下标最好都从1开始,但是排序时不要忘了此时是n+1个元素。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: