Hdu 3874 Necklace 树状数组

来源:互联网 发布:疯狂联盟座狼升星数据 编辑:程序博客网 时间:2024/05/19 22:26

题意:询问某一区间的值之和,相同元素只算一次

思路,树状数组求解,由于区间相同元素只算一次,采用离线算法,把区间右端点从小到大排序,按顺序处理。

首先我们找到一个点时,记录它的下标,若在后面还有与它相同的元素,我们把之前的元素去掉,插入到当前位置,每次进行这样的一次处理,就要判断一下,处理后该点有没有等于某一询问区间的右端点,有的话直接求,因为前面已经都处理过来了,所以该点前不存在重复的点

可是我还特别郁闷,我之前一直TLE,就是那个POS数组开小了,我还是不懂为什么

代码:

#include <stdio.h>//我无语了,那个Pos数组开小了一直TLE,可整死我了#include <iostream>#include <cstring>#include <string.h>#include <cmath>#include <vector>#include <map>#include <algorithm>using namespace std;const int M=50005;const int N=200005;int a[M];int pos[1000005];//开200005不行long long ans[N],c[M];int n,m;struct node{    int s,e,num;} inv[N];//bool cmp(node a,node b)//{//   return a.r<b.r;//}bool operator <(const node &a,const node &b){    return a.e<b.e;}int lowbit(int x){    return x&-x;}void update(int x,int v){    for(int i=x; i<=n; i+=lowbit(i))        c[i]+=v;}__int64 get_sum(int x){    __int64  s=0;    for(int i=x; i>0; i-=lowbit(i))        s+=c[i];    return s;}int nextInt()//可以优化时间{    char c;    while (c = getchar(), c < '0' || c > '9');    int r = c - '0';    while (c = getchar(), c >= '0' && c <= '9') r = r * 10 + c - '0';    return r;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=1; i<=n; i++)        {            //scanf("%d",&a[i]);            a[i]=nextInt();        }        scanf("%d",&m);        for(int i=1; i<=m; i++)        {            // scanf("%d%d",&inv[i].s,&inv[i].e);            inv[i].s=nextInt();            inv[i].e=nextInt();            inv[i].num=i;        }        sort(inv+1,inv+m+1);        memset(c,0,sizeof(c));        memset(pos,-1,sizeof(pos));        int h=1;        __int64 t1,t2;        for(int i=1; i<=n; i++)        {            if(pos[a[i]]!=-1)                update(pos[a[i]],-a[i]);            pos[a[i]]=i;            update(i,a[i]);            while(i==inv[h].e)            {                t2=get_sum(i);                t1=get_sum(inv[h].s-1);                t1=t2-t1;                ans[inv[h].num]=t1;                h++;            }        }        for(int i=1; i<=m; i++)            printf("%I64d\n",ans[i]);    }    return 0;}


原创粉丝点击