HDU3333

来源:互联网 发布:淘宝卖家火拼在哪里 编辑:程序博客网 时间:2024/06/03 14:37

8.17那天我再考场上用莫队A了这题。。。。其实是可以卡掉的。正解是线段树或树状数组。

按照询问的r排序,然后r没向右移动一次,如果这个数曾经出现了,就在这个数原来出现的地方减去这个数,再在当前位置加上这个数。

#include<cstdio>#include<cstring>#include<algorithm>#include<map>#define maxl 30010#define maxq 100010using namespace std;long long n,m,cnt;long long a[maxl],b[maxl],ans[maxq];struct que{long long l,r,num;} q[maxq];map <long long,int> pre;bool cmp(const que &x,const que &y){if(x.r==y.r)return x.l<y.l;elsereturn x.r<y.r;}void prework(){memset(b,0,sizeof(b));pre.clear();scanf("%lld",&n);for(long long i=1;i<=n;i++)scanf("%lld",&a[i]);scanf("%d",&m);for(long long i=1;i<=m;i++)scanf("%lld%lld",&q[i].l,&q[i].r),q[i].num=i;sort(q+1,q+1+m,cmp);}void add(long long i,long long x){while(i<maxl){b[i]+=x;i+=i&-i;}}long long sum(long long i){long long s=0;while(i){s+=b[i];i-=i&-i;}return s;}void mainwork(){long long r=0;for(long long i=1;i<=m;i++){while(r<q[i].r){r++;if(pre[a[r]]!=0)add(pre[a[r]],-a[r]);add(r,a[r]);pre[a[r]]=r;}ans[q[i].num]=sum(q[i].r)-sum(q[i].l-1);}}void print(){for(long long i=1;i<=m;i++)printf("%lld\n",ans[i]);}int main(){long long t;scanf("%lld",&t); for(long long i=1;i<=t;i++){prework();mainwork();print();}return 0;}