若不是题中的数看错了导致舒数组开小造成的RE,就是1A呀,话说最近总是犯这种错误,难道要换眼镜?
一看肯定是线段树,求区间内不同的数的和,由于这些数要不同,可能不是连续的,所以要离线处理。。将访问操作按照末端节点排序。。然后再把A数组离散化即可。
#include <iostream>
#include <algorithm>
#define ss(a) scanf("%d",&a)
#define cl(a) memset(a,0,sizeof(a))
#define lowbit(a) a&(-a)
#define LL __int64
using namespace std;
struct node
{
int v;
int id;
};
struct ask
{
int start;
int end;
int id;
};
const int N=30100;
const int M=100100;
int pos[N],b[N],c[N],n;
LL res[M],sum[N];
node a[N];
ask s[M];
bool cmp1(node x,node y)
{
return x.v<y.v;
}
bool cmp2(ask x,ask y)
{
return x.end<y.end;
}
void init()
{
cl(pos);cl(sum);cl(b);cl(c);cl(res);
}
LL query(int t)
{
LL re=0;
while (t>0)
{
re+=sum[t];
t-=lowbit(t);
}
return re;
}
void insert(int t,int x)
{
while (t<=n)
{
sum[t]+=x;
t+=lowbit(t);
}
}
int main()
{
int T,m,t,i,j;
ss(T);
while (T--)
{
init();
ss(n);
for (i=1;i<=n;i++)
{
ss(a[i].v);
a[i].id=i;
}
sort(a+1,a+n+1,cmp1);
t=0;
a[i].v=-1;
for (i=1;i<=n;i++)
{
if (a[i].v!=a[i-1].v) t++;
c[a[i].id]=t;
b[a[i].id]=a[i].v;
}
ss(m);
for (i=1;i<=m;i++)
{
ss(s[i].start);ss(s[i].end);
s[i].id=i;
}
sort(s+1,s+m+1,cmp2);
s[0].end=0;
for (i=1;i<=m;i++)
{
for (j=s[i-1].end+1;j<=s[i].end;j++)
{
int k=c[j];
if (!pos[k])
{
insert(j,b[j]);
}
else
{
insert(j,b[j]);
insert(pos[k],-b[j]);
}
pos[k]=j;
}
res[s[i].id]=query(s[i].end)-query(s[i].start-1);
}
for (i=1;i<=m;i++) printf("%I64d\n",res[i]);
}
return 0;
}