​点击打开链接​

 

两种做法

线段树离线处理 将查询区间右端点升序排序 然后依次遍历

每个数的值只体现在已经遍历过的序列范围内最靠右的位置 用map记录数的位置 线段树更新和查询

#include <bits/stdc++.h>
using namespace std;
#define ll long long

struct node1
{
ll ans;
int l;
int r;
int id;
};

struct node2
{
ll val;
int l;
int r;
};

map <int,int> mp;
node1 pre[100010];
node2 tree[120010];
ll num[30010];
int n;

bool cmpI(node1 n1,node1 n2)
{
return n1.r<n2.r;
}

bool cmpII(node1 n1,node1 n2)
{
return n1.id<n2.id;
}

void pushup(int cur)
{
tree[cur].val=tree[cur*2].val+tree[cur*2+1].val;
return;
}

void build(int l,int r,int cur)
{
int m;
tree[cur].val=0;
tree[cur].l=l;
tree[cur].r=r;
if(l==r) return;
m=(l+r)/2;
build(l,m,cur*2);
build(m+1,r,cur*2+1);
return;
}

void update(int tar,ll val,int cur)
{
if(tree[cur].l==tree[cur].r)
{
tree[cur].val+=val;
return;
}
if(tar<=tree[cur*2].r) update(tar,val,cur*2);
else update(tar,val,cur*2+1);
pushup(cur);
return;
}

ll query(int pl,int pr,int cur)
{
ll res;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
res=0;
if(pl<=tree[cur*2].r) res+=query(pl,pr,cur*2);
if(pr>=tree[cur*2+1].l) res+=query(pl,pr,cur*2+1);
return res;
}

int main()
{
int t,q,i,j,p;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
mp.clear();
build(1,n,1);
for(i=1;i<=n;i++)
{
scanf("%lld",&num[i]);
}
scanf("%d",&q);
for(i=1;i<=q;i++)
{
scanf("%d%d",&pre[i].l,&pre[i].r);
pre[i].id=i;
}
sort(pre+1,pre+q+1,cmpI);
p=1;
for(i=1;i<=q;i++)
{
while(p<=pre[i].r)
{
if(mp[num[p]]!=0)
{
update(mp[num[p]],-num[p],1);
}
mp[num[p]]=p;
update(p,num[p],1);
p++;
}
pre[i].ans=query(pre[i].l,pre[i].r,1);
}
sort(pre+1,pre+q+1,cmpII);
for(i=1;i<=q;i++)
{
printf("%lld\n",pre[i].ans);
}
}
return 0;
}

 

主席树也有两种写法 详见代码 还是所有数都尽量向一侧靠拢 还有HDU上交G++会RE到死

#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long

struct node
{
int l;
int r;
ll val;
};

map <ll,int> mp;
node tree[1000010];
ll ary[30010];
int root[30010];
int n,q,num;

int build(int l,int r)
{
int cur,m;
cur=num++;
tree[cur].l=0,tree[cur].r=0,tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].l=build(l,m);
tree[cur].r=build(m+1,r);
return cur;
}

int update(int rot,int tar,ll val,int l,int r)
{
int cur,m;
cur=num++;
tree[cur]=tree[rot];
tree[cur].val+=val;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
return cur;
}

ll query(int rot,int pl,int pr,int l,int r)
{
ll res;
int m;
if(pl<=l&&r<=pr)
{
return tree[rot].val;
}
res=0,m=(l+r)/2;
if(pl<=m) res+=query(tree[rot].l,pl,pr,l,m);
if(pr>=m+1) res+=query(tree[rot].r,pl,pr,m+1,r);
return res;
}

int main()
{
int t,i,l,r;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lld",&ary[i]);
}
mp.clear();
num=0;
root[0]=build(1,n);
for(i=1;i<=n;i++)
{
if(mp[ary[i]]!=0)
{
root[i]=update(root[i-1],mp[ary[i]],-ary[i],1,n);
root[i]=update(root[i],i,ary[i],1,n);
}
else
{
root[i]=update(root[i-1],i,ary[i],1,n);
}
mp[ary[i]]=i;
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&l,&r);
printf("%lld\n",query(root[r],l,r,1,n));
}
}
return 0;
}

 

#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=3e4+10;

struct node
{
ll val;
int l,r;
};

map <ll,int> mp;
node tree[20*maxn];
int root[maxn];
int n,q,num;

int build(int l,int r)
{
int cur,m;
cur=num++;
tree[cur].l=tree[cur].r=tree[cur].val=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].l=build(l,m);
tree[cur].r=build(m+1,r);
return cur;
}

int update(int rot,int tar,ll val,int l,int r)
{
int cur,m;
cur=num++;
tree[cur]=tree[rot];
tree[cur].val+=val;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
return cur;
}

ll query(int lrot,int rrot,int pl,int pr,int l,int r)
{
ll res;
int m;
if(pl<=l&&r<=pr){
return tree[rrot].val-tree[lrot].val;
}
res=0,m=(l+r)/2;
if(pl<=m) res+=query(tree[lrot].l,tree[rrot].l,pl,pr,l,m);
if(pr>m) res+=query(tree[lrot].r,tree[rrot].r,pl,pr,m+1,r);
return res;
}

int main()
{
ll val;
int t,i,l,r;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
mp.clear();
num=0;
root[0]=build(0,n-1);
for(i=1;i<=n;i++){
scanf("%lld",&val);
root[i]=update(root[i-1],mp[val],val,0,n-1);
mp[val]=i;
}
scanf("%d",&q);
while(q--){
scanf("%d%d",&l,&r);
printf("%lld\n",query(root[l-1],root[r],0,l-1,0,n-1));
}
}
return 0;
}