HDU3333 Turing Tree 离线树状数组

题意:统计一段区间内不同的数的和

分析:排序查询区间,离线树状数组

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 3e4+5;
const int mod = 1e9+7;
LL c[N];
int n,q,x,y,T,pre[N];
struct Node{
  int v,id;
}a[N];
bool cmpv(Node a,Node b){
  if(a.v==b.v)return a.id<b.id;
  return a.v<b.v;
}
bool cmpid(Node a,Node b){
  return a.id<b.id;
}
void add(int x,LL t){
  for(int i=x;i<=n;i+=i&(-i))c[i]+=t; 
}
LL ask(int x){
  LL ret=0;
  for(int i=x;i;i-=i&(-i))ret+=c[i];
  return ret;
}
struct Que{
  int l,r,id;
  bool operator<(const Que &rhs)const{
    return r<rhs.r;
  }
}p[100000];
LL ret[100000];
int main(){
  scanf("%d",&T);
  while(T--){
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",&a[i].v),a[i].id=i;
    sort(a+1,a+1+n,cmpv);
    for(int i=1;i<=n;++i){
      pre[a[i].id]=-1;
      if(i!=1&&a[i].v==a[i-1].v)pre[a[i].id]=a[i-1].id;
    }
    sort(a+1,a+1+n,cmpid);
    memset(c,0,sizeof(c));
    scanf("%d",&q);
    for(int i=0;i<q;++i)scanf("%d%d",&p[i].l,&p[i].r),p[i].id=i;
    sort(p,p+q);
    for(int i=0,cur=1;i<q;++i){
      for(;cur<=p[i].r;++cur){
         if(pre[cur]!=-1)add(pre[cur],-a[cur].v);
         add(cur,a[cur].v);
      }
      ret[p[i].id]=ask(p[i].r)-ask(p[i].l-1);
    }
    for(int i=0;i<q;++i)printf("%I64d
",ret[i]);  
  }
  return 0;
}
View Code
原文地址:https://www.cnblogs.com/shuguangzw/p/5741746.html