现在给定一个N个数的序列A1 A2…,和大量的查询(i,j)(j 1≤≤≤N)。对于每个查询(i, j),你要计算子序列Ai, Ai+1,…Aj。——重复的数只能算一次。
输入
第一行是一个整数T(1≤T≤10),indecating以下测试点的数量。
对于每种情况,输入格式如下:
1:N(1≤N≤30000)。
第2行:N个整数A1, A2,…,一个Ai(0≤≤1000000000)。
3行:Q Q(1≤≤100000),查询的数量。
接下来问:每一行包含2整数,j代表一个查询(j 1≤≤≤N)。
输出
对于每个查询,在一行中打印指定子序列的不同值的和。
题解:
因为不允许重复 所以需要有清0操作。边插入(update),清零(update)。边询问。
离线处理多次询问。离散化处理Ai 以便存入到vis[],dex[]中。
将区间的右端点从小到大将区间排序。比如序列 1 3 3 2 3。查询(2,3) ; (3,5)。
查询(2,3)在插入1 3 3 的时候插入第二个3的时候就会把第一个3清0。插入 2 3时会把第二个3清0。
假如先查询 (3,5)。会在第一次查询时把第一个第二个3都清0。无法查询(2,3)。
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdio>
#define m(a,b) memset(a,b,sizeof a)
typedef long long ll;
using namespace std;
const int N=30005*4;
ll ans[N],cur[N],tmp[N],fin[N],dex[N];//ans 线段树里面的数组 cur数据值 tmp排序后的数据值以便reflect fin储存询问的答案
bool vis[N];//判断当前状态下 i 所映射的数是否出现在线段树里面.若出现,则出现的位置是 dex[i] 这里都将采用了离散化了
struct interval
{
int l,r,id; //离线处理多次询问 把需要的区间按右端点从小到大排序 区间打乱 故需要一个id.
}span[N]; // span[i].id为是这一次的询问 fin[span[i].id]即为所求、
bool cmp(interval a,interval b)
{
return a.r<b.r;
}
ll query(int cl,int cr,int l,int r,int pos)
{
if(cl<=l&&r<=cr)
return ans[pos];
int mid=(l+r)>>1;
ll ans=0;
if(cl<=mid)
ans+=query(cl,cr,l,mid,pos<<1);
if(cr>mid)
ans+=query(cl,cr,mid+1,r,pos<<1|1);
return ans;
}
void update(int n,ll val,int l,int r,int pos)
{
if(l==r)
{
ans[pos]=val;
return;
}
int mid=(l+r)>>1;
if(n<=mid)
update(n,val,l,mid,pos<<1);
else
update(n,val,mid+1,r,pos<<1|1);
ans[pos]=ans[pos<<1]+ans[pos<<1|1];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
m(vis,0);
int n,m;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&cur[i]),tmp[i]=cur[i];//添加一个数的时候需要判断他是否已经在线段树里面,故要有vis[],假如有的话dex[]为这个数存在的位置
sort(tmp+1,tmp+n+1); //是为了 将超级大的数用他在tmp数组排序后的位置reflect。
scanf("%d",&m);
for(int i=1;i<=m;i++) //用lower_bound()函数正好可以去重啊。。因为多个数映射到同一位置。肯定是这些数一样啊
scanf("%d%d",&span[i].l,&span[i].r),span[i].id=i;
sort(span+1,span+m+1,cmp);
int j=1;
for(int i=1;i<=n;i++)
{
int refl=lower_bound(tmp+1,tmp+n+1,cur[i])-(tmp+1);
if(!vis[refl])
{
vis[refl]=1;
update(i,cur[i],1,n,1);
dex[refl]=i;
}
else
{
update(dex[refl],0,1,n,1);
update(i,cur[i],1,n,1);
dex[refl]=i;
}
for(;j<=m;j++)
{
if(i!=span[j].r)
break;
fin[span[j].id]=query(span[j].l,span[j].r,1,n,1);
}
}
for(int i=1;i<=m;i++)
printf("%lld\n",fin[i]);
}
}