hdu (3874)树状数组

来源:互联网 发布:python打开谷歌浏览器 编辑:程序博客网 时间:2024/05/18 02:58

求区间【L,R】的不同的数的和。

解答:这题没有离散化。先记录该位置出现的数字往前最近出现的位置,然后按查询的的右端点排序,最后一次扫描各个点同时检查右端点在该位置的询问。

#include <iostream>#include <cstring>#include <vector>#include <cstdio>#include <map>#include <algorithm>#define LL __int64using namespace std;const int N=50090;LL C[N+100];int ss[1000006];//记录位置int n,q;int val[N];int pre[N];//记录前驱val【I】的位置struct Node{    int L,R;    int id;}Q[209008];bool cmp(Node a,Node b){    return a.R<b.R;}LL ans[209008];int lowbit(int a){    return a&(-a);}LL getsum(int p){    LL ans=0;    for(int i=p;i>0;i-=lowbit(i))    ans+=C[i];    return ans;}void Modify(int p,int c){    for(int i=p;i<=n+2;i+=lowbit(i))     C[i]+=c;}int in(){    char ch;    int a = 0;    while((ch = getchar()) == ' ' || ch == '\n');    a += ch - '0';    while((ch = getchar()) != ' ' && ch != '\n')    {        a *= 10;        a += ch - '0';    }    return a;}int main(){    int cas;    cas=in();    int  T=0;    while(cas--)    {     memset(ss,0,sizeof(ss));     memset(C,0,sizeof(C));      n=in();      for(int i=1;i<=n;i++)      {        val[i]=in();        if(ss[val[i]]==0)        {            ss[val[i]]=i;            pre[i]=ss[val[i]];        }        else        {            pre[i]=ss[val[i]];            ss[val[i]]=i;        }      }     q=in();     for(int i=1;i<=q;i++)     {         Q[i].L=in();         Q[i].R=in();         Q[i].id=i;     }     sort(Q+1,Q+q+1,cmp);     int cnt=1;     for(int i=1;i<=n;i++)     {        int v=val[i];        int p=pre[i];        if(p==i)          Modify(p,v);        else        {          Modify(p,-v);          Modify(i,v);        }        while(Q[cnt].R==i)        {              ans[Q[cnt].id]=getsum(Q[cnt].R)-getsum(Q[cnt].L-1);              cnt++;        }     }     for(int i=1;i<=q;i++)       printf("%I64d\n",ans[i]);   }    return 0;}

原创粉丝点击