HDU 3874 离线线段树

统计区间内所有数字和,对于重复出现的只统计一次

线段树的离线算法

按结束坐标排序,然后扫一遍,遇到重复的,就把之前插入线段树的给删掉

#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;

struct node
{
    int l,r;
    __int64 sum;
}data[200010];

struct Mark
{
    int l,r,id;
}mark[200010];

int hash[1000001];
__int64 a[50010],ans[200010];
bool cmp(Mark a,Mark b)
{
    return a.r<b.r;
}

void build (int l,int r,int k)
{
    int mid;
    data[k].l=l;
    data[k].r=r;
    data[k].sum=0;

    if (l==r) return ;
    mid=(l+r)/2;

    build(l,mid,k*2);
    build(mid+1,r,k*2+1);
}

void updata(int n,int k,int op)
{
    int mid;
    if (data[k].l==n && data[k].r==n)
    {
        data[k].sum+=op;
        return ;
    }

    mid=(data[k].l+data[k].r)/2;
    if (n<=mid) updata(n,k*2,op);
    else updata(n,k*2+1,op);

    data[k].sum=data[k*2].sum+data[k*2+1].sum;
}

__int64 query(int l,int r,int k)
{
    int mid;
    if (data[k].l==l && data[k].r==r)
        return data[k].sum;
    mid=(data[k].l+data[k].r)/2;

    if (r<=mid) return query(l,r,k*2);
    else
        if (l>mid) return query(l,r,k*2+1);
    else
        return query(l,mid,k*2)+query(mid+1,r,k*2+1);
}

int main()
{
    int Case,i,n,m,now;

    scanf("%d",&Case);
    while (Case--)
    {
        scanf("%d",&n);
        for (i=1;i<=n;i++)
            scanf("%I64d",&a[i]);
        scanf("%d",&m);
        for (i=0;i<m;i++)
        {
            scanf("%d%d",&mark[i].l,&mark[i].r);
            mark[i].id=i;
        }
        sort(mark,mark+m,cmp);

        build(1,50000,1);
        memset(hash,0,sizeof(hash));
        now=1;
        for (i=0;i<m;i++)
        {
            while (now<=mark[i].r)
            {
                if (hash[a[now]]!=0)
                    updata(hash[a[now]],1,-a[now]);
                hash[a[now]]=now;
                updata(now,1,a[now]);
                now++;
            }
            ans[mark[i].id]=query(mark[i].l,mark[i].r,1);
        }
        for (i=0;i<m;i++)
            printf("%I64d\n",ans[i]);
    }
    return 0;
}
时间: 2024-11-10 01:35:25

HDU 3874 离线线段树的相关文章

Necklace HDU - 3874 (线段树/树状数组 + 离线处理)

Necklace HDU - 3874 Mery has a beautiful necklace. The necklace is made up of N magic balls. Each ball has a beautiful value. The balls with the same beautiful value look the same, so if two or more balls have the same beautiful value, we just count

HDU - 3874 Necklace (线段树 + 离线处理)

欢迎参加--每周六晚的BestCoder(有米!) Necklace Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4003    Accepted Submission(s): 1330 Problem Description Mery has a beautiful necklace. The necklace is made

hdu 4638 Group(莫队算法|离线线段树)

Group Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1323    Accepted Submission(s): 703 Problem Description There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-

HDU 4417 Super Mario(离线线段树or树状数组)

Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss's castle as a l

HDU ACM 4417 Super Mario 离线线段树

分析:离线线段树,把所有询问离线读入,然后按H从小到大排序.对于所有结点也按从小到大排序,然后根据查询的H,将比H小的点加入到线段树,最后就是一个区间求和.这题貌似也可以用划分树,树状数组等方法做. #include<iostream> #include<algorithm> using namespace std; #define N 100005 struct Tree { int left,right,cnt; } TREE[N<<2]; struct Query

UPC 2224 Boring Counting (离线线段树,统计区间[l,r]之间大小在[A,B]中的数的个数)

题目链接:http://acm.upc.edu.cn/problem.php?id=2224 题意:给出n个数pi,和m个查询,每个查询给出l,r,a,b,让你求在区间l~r之间的pi的个数(A<=pi<=B,l<=i<=r). 参考链接:http://www.cnblogs.com/zj62/p/3558967.html #include <iostream> #include <cstdio> #include <cstring> #incl

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

27号的十道离线线段树

27号的十道离线线段树 hdu4288: (2012成都网络赛&&cf) #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m