HDU 3333 (线段树)

xiaoxiao2025-04-11  13

题意:

询问一个区间中的不同数的和,例如 1 1 1 2 3 这个区间的和为6

分析:

离线处理,按照右区间端点值进行排序,然后记录之前这个点是否出现过进行更改。然后最后查询区间和。

处理完后就是很普通的线段树单点操作区间求和。

#include<bits/stdc++.h> using namespace std; const int maxn=3e4; typedef long long ll; int a[maxn]; struct node{ int l,r,id; }q[100005]; ll ans[100005]; ll tree[maxn<<2]; bool cmp(node x,node y){ return x.r<y.r; } void update(int l,int r,int i,int x,int y){ if(l==r){ tree[i]+=y; return ; } int mid=l+r>>1; if(x<=mid) update(l,mid,i<<1,x,y); else update(mid+1,r,i<<1|1,x,y); tree[i]=tree[i<<1]+tree[i<<1|1]; } ll query(int l,int r,int i,int x,int y){ if(l>y||r<x) return 0; if(l>=x&&r<=y){ return tree[i]; } int mid=l+r>>1; return query(l,mid,i<<1,x,y)+query(mid+1,r,i<<1|1,x,y); } int main(){ int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } scanf("%d",&m); for(int i=0;i<m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q,q+m,cmp); map<int,int> mp; int p=0,x,y; memset(tree,0,sizeof tree); for(int i=0;i<m;i++){ while(p<q[i].r){ p++; if(mp.count(a[p])){ x=mp[a[p]];y=-a[p]; update(1,n,1,x,y); } x=p,y=a[p]; update(1,n,1,x,y); mp[a[p]]=p; } x=q[i].l;y=q[i].r; ans[q[i].id]=query(1,n,1,x,y); } for(int i=0;i<m;i++){ printf("%lld\n",ans[i]); } } return 0; }

 

转载请注明原文地址: https://www.6miu.com/read-5028036.html

最新回复(0)