http://acm.hdu.edu.cn/showproblem.php?pid=3874
这题题目是好题呀!可以我想不出来,看了网上的题解才明白!
当时我想的是枚举从1 到 当前 r 区间中只出现一次的和,但是对于 询问 【l ,r】就 如果某个数在 只在[ 1 , L-1] 或者 [ l , r ] 区间出现答案都正确,但是对于 有些数 在两个区间都出现的话,一减的话相当于没有出现,答案就不对了…… 看了网上的解题办法,是这样的话,如果当前的数之前出现的话,那么把之前的位置处减去,然后再当前位置插入……
离线查询
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define lowbit(x) x&(-x)
const int maxn=500100;
typedef long long ll;
ll d[maxn],ans[maxn];
int n,last[1000010],a[maxn];
struct Node
{
int l,r,id;
}node[200010];
int cmp(Node a,Node b)
{
if(a.r!=b.r) return a.r < b.r;
return a.l < b.l;
}
void add(int p,int val)
{
for(int i=p;i<=n;i+=lowbit(i))
d[i]+=val;
}
ll query(int p)
{
ll sum=0;
for(int i=p;i>=1;i-=lowbit(i))
sum+=d[i];
return sum;
}
int main()
{
int m,ca;
scanf("%d",&ca);
while(ca--)
{
scanf("%d",&n);
memset(d,0,sizeof(d));
memset(last,-1,sizeof(last));
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=0;i<m;i++)
scanf("%d %d",&node[i].l,&node[i].r),node[i].id=i;
sort(node,node+m,cmp);
int r=1;
for(int i=0;i<m;i++)
{
while(r<=node[i].r)
{
if(last[a[r]]!=-1) add(last[a[r]],-a[r]);
last[a[r]]=r;
add(r,a[r]);
r++;
}
ans[node[i].id]=query(node[i].r)-query(node[i].l-1);
}
for(int i=0;i<m;i++)
printf("%I64d\n",ans[i]);
}
return 0;
}