HDU 3874 Necklace

来源:互联网 发布:软件订阅模式 编辑:程序博客网 时间:2024/05/22 03:25

HDU 3874 Necklace

线段树,离线询问

题意

给一个数组,m个询问。每次询问一个区间,求区间内数的和,重复数只计算一次。

思路

离线询问后按右端点排序,从左往右扫数字,开个hash记录上次该数出现的位置。线段树模拟数组,出现就在位置上放数,没出现就置零,统计区间和。

这样每次扫到一个数,如果他没出现,就放到线段树上;如果他出现了,那么把它从上次出现的位置删掉,放到新的位置,更新hash数组。

每次询问统计区间和。

代码

1A就是美滋滋

#include<bits/stdc++.h>#define M(a,b) memset(a,b,sizeof(a))#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1typedef long long LL;using namespace std;const int MAXN=50007;const int oo=0x3f3f3f3f;LL stree[MAXN<<2];void pushup(int rt){    stree[rt]=stree[rt<<1]+stree[rt<<1|1];}void build(int l, int r, int rt){    M(stree, 0);}void update(int pos, int c, int l, int r, int rt){    if(l==r) { stree[rt]+=c;return; }    int mid=(l+r)>>1;    if(pos<=mid) update(pos, c, lson);    else update(pos, c, rson);    pushup(rt);}LL query(int L, int R, int l, int r, int rt){    if(L<=l&&r<=R) return stree[rt];    int mid=(l+r)>>1;    LL res=0;    if(L<=mid) res+=query(L, R, lson);    if(mid<R) res+=query(L, R, rson);    return res;}int num[MAXN];int ha[1000007];struct Query{    int l, r;    LL ans;    int ne;}q[MAXN<<2];int head[MAXN];int main(){    int T;scanf("%d", &T);    while(T--)    {        int n;scanf("%d", &n);        for(int i=1;i<=n;i++)            scanf("%d", &num[i]);        int m;scanf("%d", &m);        build(1, n, 1);        M(head, -1), M(ha, 0);        for(int i=1;i<=m;i++)        {            scanf("%d%d", &q[i].l, &q[i].r);q[i].ans=0;            q[i].ne=head[q[i].r];head[q[i].r]=i;        }        for(int i=1;i<=n;i++)        {            if(ha[num[i]]==0)            {                update(i, num[i], 1, n, 1);                ha[num[i]]=i;            }            else            {                update(ha[num[i]], -num[i], 1, n, 1);                update(i, num[i], 1, n, 1);                ha[num[i]]=i;            }            for(int j=head[i];~j;j=q[j].ne)            {                int l=q[j].l, r=q[j].r;                q[j].ans=query(l, r, 1, n, 1);            }        }        for(int i=1;i<=m;i++)        {            printf("%lld\n", q[i].ans);        }    }    return 0;}
原创粉丝点击