hdu 3874 Necklace 线段树单点更新区间求和

http://acm.hdu.edu.cn/showproblem.php?pid=3874

题意:

给你n个数,然后给出m个的询问[l,r]问[l,r]中不同的数的和为多少?

思路:
单纯只考虑不同数的和的话,可能该数在之前出现过,后边又出现了,但是所求的区间不包括前边那个数,那么这个数就要被加进来。关键是如何维护该区间不包含重复计算同一个数。

首先我们离线处理所有询问,然后按r排序,然后遍历一边处理那些还没被加进线段树的数,如果他之前出现过了,那么就将之前的删除,然后再吧后边的加进来,这样既能保证同一个数只被计算的一次了,而且不影响后边的询问。

这里关键是按r排序之后的处理:

#include <iostream>

#include <cstdio>

#include <cmath>

#include <vector>

#include <cstring>

#include <algorithm>

#include <string>

#include <set>

#include <functional>

#include <numeric>

#include <sstream>

#include <stack>

#include <map>

#include <queue>



#define CL(arr, val) memset(arr, val, sizeof(arr))



#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define L(x)    (x) << 1

#define R(x)    (x) << 1 | 1

#define MID(l, r)   (l + r) >> 1

#define Min(x, y)   (x) < (y) ? (x) : (y)

#define Max(x, y)   (x) < (y) ? (y) : (x)

#define E(x)        (1 << (x))

#define iabs(x)     (x) < 0 ? -(x) : (x)

#define OUT(x)  printf("%I64d\n", x)

#define lowbit(x)   (x)&(-x)

#define Read()  freopen("din.txt", "r", stdin)

#define Write() freopen("dout.txt", "w", stdout)





#define M 200007

#define N 50007

#define ll __int64

using namespace std;

const double eps = 1e-10;



struct node

{

    int l,r;

    int id;

}nd[M];



ll val[4*N];

ll ans[M];

int a[N];

int off[1000007];



int n;



void pushup(int rt)

{

    val[rt] = val[rt<<1] + val[rt<<1|1];

}

void build(int l,int r,int rt)

{

    val[rt] = 0;

    if (l == r) return ;

    int m = (l + r)>>1;

    build(lc);

    build(rc);

}

void update(int pos,ll sc,int l,int r,int rt)

{

    if (l == r)

    {

        val[rt] += sc;

        return ;

    }

    int m = (l + r)>>1;

    if (pos <= m) update(pos,sc,lc);

    else update(pos,sc,rc);

    pushup(rt);

}

ll query(int L,int R,int l,int r,int rt)

{

    if (l >= L && r <= R) return val[rt];

    ll res = 0;

    int m = (l + r)>>1;

    if (L <= m) res += query(L,R,lc);

    if (R > m) res += query(L,R,rc);

    return res;

}



int cmp(node a,node b) { return a.r < b.r; }

int cmp2(node a,node b) { return a.id < b.id; }



int main()

{

//    Read();

    int i;

    int T,n,m;

    scanf("%d",&T);

    while (T--)

    {

        scanf("%d",&n);

        for (i = 1; i <= n; ++i) scanf("%d",&a[i]);

        scanf("%d",&m);

        for (i = 0; i < m; ++i)

        {

            scanf("%d%d",&nd[i].l,&nd[i].r);

            nd[i].id = i;

        }



        sort(nd,nd + m,cmp);

        build(1,n,1);

        CL(off,0);



        int s = 1;

        for (i = 0; i < m; ++i)

        {

            while (s <= nd[i].r)

            {

                if (off[a[s]]) update(off[a[s]],-a[s],1,n,1);



                update(s,a[s],1,n,1);

                off[a[s]] = s;

                s++;

            }

            ans[nd[i].id] = query(nd[i].l,nd[i].r,1,n,1);

        }



        for (i = 0; i < m; ++i)

        {

            printf("%I64d\n",ans[i]);

        }

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(HDU)