Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1973 Accepted Submission(s): 654
//这题的做法是先离散化,然后把Q按右边端点进行升序排序
//这是把数据一个个插入、遇到以前出现了的数字,就删除原来的位置的值,在新位置插入
//这样做法的正确性和按Q的右端点排序有关
//遇到坐标和Q右端点相等时就可以完成query,并且保存
//最后按输入小标排序,并输出结果,树状数组比线段树快些
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 33334//我开始把这写成3333,然后后面Q的区间数组有N*3
#define lson l,m,k<<1 //我很二的以为这样已经超过10W了,然后纠结了一下午,
#define rson m+1,r,k<<1|1 //抓狂、、、这题好多3,真被伤到了
using namespace std;
__int64 st[N<<2];
int rc[N],sv[N],rci[N];
bool hash[N];
struct node
{
int i,j;
int index;
__int64 ans;
bool operator<(const node&a)const
{
return j<a.j;
}
};
node interval[N*3];
int n;
int bf(int &val)
{
int l=1,r=n,m;
while(l<=r)
{
m=(l+r)>>1;
if(rc[m]>val) r=m-1;
else if(rc[m]<val) l=m+1;
else return m;
}
}
bool cmp(const node&a,const node&b)
{
return a.index<b.index;
}
void build(int l,int r,int k)
{
st[k]=0;
if(l==r)
return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void up(int &k)
{
st[k]=st[k<<1]+st[k<<1|1];
}
int flag;
void update(int index,int l,int r,int k)
{
if(l==r)
{
st[k]=flag;//printf(" flag%.lf ",flag);
return;
}
int m=(l+r)>>1;
if(index<=m) update(index,lson);
else update(index,rson);
up(k);
}
double query(int &L,int &R,int l,int r,int k)
{
if(L<=l&&R>=r)
{
return st[k];
}
int m=(l+r)>>1;
double t1=0,t2=0;
if(L<=m) t1=query(L,R,lson);
if(R>m) t2=query(L,R,rson);
return t1+t2;
}
int main()
{
int T;
int Q;
int i,k,rcn;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);rcn=n;
for(i=1;i<=n;i++)
scanf("%d",&rc[i]),sv[i]=rc[i],hash[i]=0;
sort(rc+1,rc+n+1);
for(k=1,i=2;i<=n;i++)
if(rc[i]!=rc[k])
rc[++k]=rc[i];
n=k;
scanf("%d",&Q);
for(i=0;i<Q;i++)
{
scanf("%d%d",&interval[i].i,&interval[i].j);
interval[i].index=i;
}
sort(interval,interval+Q);
//interval[Q].j=-1;
build(1,rcn,1);
k=0;int temp;
for(i=1;i<=rcn;i++)
{
temp=bf(sv[i]);
if(hash[temp])
{
flag=0;
update(rci[temp],1,rcn,1);
flag=sv[i];
rci[temp]=i;
update(i,1,rcn,1);
}
else
{
hash[temp]=1;
flag=sv[i];
rci[temp]=i;
update(i,1,rcn,1);
}
while(i==interval[k].j)
{
interval[k].ans=query(interval[k].i,interval[k].j,1,rcn,1);
k++;
if(k>=Q) break;
}
if(k>=Q) break;
}
sort(interval,interval+Q,cmp);
for(i=0;i<Q;i++)
printf("%I64d\n",interval[i].ans);
}
return 0;
}
//改用树状数组做、快了200Ms吧
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 33334
using namespace std;
struct node
{
int i,j;
int index;
__int64 ans;
bool operator<(const node&a)const
{
return j<a.j;
}
};
node interval[N*3];
int n,rcn;
__int64 c[N];
int rc[N],sv[N],rci[N];
int lb[N];
bool hash[N];
int bf(int &val)
{
int l=1,r=n,m;
while(l<=r)
{
m=(l+r)>>1;
if(rc[m]>val) r=m-1;
else if(rc[m]<val) l=m+1;
else return m;
}
}
bool cmp(const node&a,const node&b)
{
return a.index<b.index;
}
void update(int index,int val)
{
for(;index<=rcn;index+=lb[index])
c[index]+=val;
}
__int64 r_sum(int index)
{
__int64 sum=0;
for(;index>0;index-=lb[index])
sum+=c[index];
return sum;
}
int main()
{
int T;
int Q;
int i,k;
for(i=1;i<=30000;i++)lb[i]=i&(-i);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);rcn=n;
for(i=1;i<=n;i++)
{
scanf("%d",&rc[i]);
sv[i]=rc[i];
hash[i]=0;
c[i]=0;
}
sort(rc+1,rc+n+1);
for(k=1,i=2;i<=n;i++)
if(rc[i]!=rc[k])
rc[++k]=rc[i];
n=k;
scanf("%d",&Q);
for(i=0;i<Q;i++)
{
scanf("%d%d",&interval[i].i,&interval[i].j);
interval[i].index=i;
}
sort(interval,interval+Q);
k=0;int temp;
for(i=1;i<=rcn;i++)
{
temp=bf(sv[i]);
if(hash[temp])
{
update(rci[temp],-sv[i]);
rci[temp]=i;
update(i,sv[i]);
}
else
{
hash[temp]=1;
rci[temp]=i;
update(i,sv[i]);
}
while(i==interval[k].j)
{
interval[k].ans=r_sum(interval[k].j)-r_sum(interval[k].i-1);
k++;
if(k>=Q) break;
}
if(k>=Q) break;
}
sort(interval,interval+Q,cmp);
for(i=0;i<Q;i++)
printf("%I64d\n",interval[i].ans);
}
return 0;
}