题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和

分析 :

一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序

最后从左到右将原区间扫一遍,扫的过程当中不断将重复出现的数字右移

也就是如果一个数字重复出现,那么我们记录最右边的那个为有效的,其他都视为不存在

这样一旦遇到一个问询区间的右端点就线段树查询即可。

SPOJ:

#include<bits/stdc++.h>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
;
];
void PushUP(int rt) {
    sumv[rt] = sumv[rt<<] + sumv[rt<<|];
}
void update(int p,int sc,int l,int r,int rt) {
    if (l == r) {
        sumv[rt] += sc;
        return ;
    }
    );
    if (p <= m) update(p , sc , lson);
    else update(p , sc , rson);
    PushUP(rt);
}

long long query(int L,int R,int l,int r,int rt) {
    if (L <= l && r <= R) {
        return sumv[rt];
    }
    );
    ;
    if (L <= m) ret += query(L , R , lson);
    if (R > m) ret += query(L , R , rson);
    return ret;
}
struct Interval{
    int l, r, id;
    bool operator < (const Interval& other) const{
        return this->r < other.r;
    }
};
Interval sec[];
map<int, int> mp;
int arr[maxn];
int pre[maxn];
long long ans[maxn];
int main(void)
{
    , m;
    scanf("%d", &n);
    ; i<=n; i++){
        scanf("%d", &arr[i]);
        if(!mp.count(arr[i]))
            mp[arr[i]] = cnt++;//区间上的每一个数都有一个独特的编号,使用map来进行映射,目的是方便判断此数是否已经重复出现过
    }
    scanf("%d", &m);
    ; i<=m; i++){
        scanf("%d %d", &sec[i].l, &sec[i].r);
        sec[i].id = i;//因为后续有排序操作,而我们又要对问询答案顺序给出,所以记录给出的顺序,方便输出答案
    }
    sort(sec+, sec++m);//按照右端点排序
    bool vis[maxn];
    memset(vis, false, sizeof(vis));
    , j=; j<=m && i<=n; i++){
        int tmp = mp[arr[i]];//拿出这个数的编号
        if(vis[tmp]){//如果这个数在前面已经访问过
            update(pre[tmp], -, , n, );//将之前的位置信息抹去
            update(i, , , n, );//当前的位置才是有效的,所以给当前位置+1
            pre[tmp] = i;//更新pre数组方便下次操作
        }else{
            vis[tmp] = true;
            update(i, , , n, );
            pre[tmp] = i;
        }
        while(sec[j].r == i){
            ans[sec[j].id] = query(sec[j].l, sec[j].r, , n, );
            j++;
        }
    }
    ; i<=m; i++){
        printf("%I64d\n", ans[i]);
    }

    ;
}

HDU:

#include<bits/stdc++.h>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
;
];
void PushUP(int rt) {
    sumv[rt] = sumv[rt<<] + sumv[rt<<|];
}
void update(int p,long long sc,int l,int r,int rt) {
    if (l == r) {
        sumv[rt] += sc;
        return ;
    }
    );
    if (p <= m) update(p , sc , lson);
    else update(p , sc , rson);
    PushUP(rt);
}
long long query(int L,int R,int l,int r,int rt) {
    if (L <= l && r <= R) {
        return sumv[rt];
    }
    );
    ;
    if (L <= m) ret += query(L , R , lson);
    if (R > m) ret += query(L , R , rson);
    return ret;
}
struct interval{
    int L, R, id;
    bool operator < (const interval & other) const{
        return this->R < other.R;
    }
};
interval sec[maxn<<];
bool vis[maxn];
];
int per[maxn];
long long arr[maxn];
map<long long, int> mp;
int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    while(nCase--){
        int n;
        mp.clear(); ;
        memset(sumv, , sizeof(sumv));
        scanf("%d", &n);
        ; i<=n; i++){
            scanf("%I64d", &arr[i]);
            if(!mp.count(arr[i]))
                mp[arr[i]] = cnt++;
        }
        int m;
        scanf("%d", &m);
        ; i<=m; i++){
            scanf("%d %d", &sec[i].L, &sec[i].R);
            sec[i].id = i;
        }
        sort(sec+, sec++m);
        memset(vis, false, sizeof(vis));
        , j=; j<=m && i<=n; i++){
            int num = mp[arr[i]];
            if(vis[num]){
                update(per[num],-arr[i],,n,);
                update(i, arr[i], , n, );
                per[num] = i;
            }else{
                vis[num] = true;
                update(i, arr[i], , n, );
                per[num] = i;
            }
            while(i==sec[j].R){
                ans[sec[j].id] = query(sec[j].L, sec[j].R, , n, );
                j++;
            }
        }
        ; i<=m; i++){
            printf("%I64d\n", ans[i]);
        }
    }
}

update in 2018-06-08

学了主席树、以上的离线算法都可以变成在线算法了、戳 主席树

SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)的更多相关文章

  1. HDU 3333 Turing Tree 线段树+离线处理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...

  2. HDU 3333 Turing Tree (线段树)

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. HDU 3333 Turing Tree(树状数组/主席树)

    题意 给定一个长度为 \(n​\) 的序列,\(m​\) 个查询,每次查询区间 \([L,R]​\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...

  4. HDU 3333 Turing Tree (主席树)

    题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...

  5. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  6. W同学的新画板 QDUOJ 线段树 区间颜色段数

    W同学的新画板 QDUOJ 线段树 区间颜色段数 原题链接 题意 W同学在每天的刻苦学习完成功课之余,都会去找一些有趣的事情来放松自己:恰巧今天他收到了朋友送给他的一套画板,于是他立刻拆开了包装,拿出 ...

  7. hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)

    http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others)    ...

  8. hdu 3333 Turing Tree(线段树+离散化)

    刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望. 刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的 ...

  9. HDU 6638 - Snowy Smile 线段树区间合并+暴力枚举

    HDU 6638 - Snowy Smile 题意 给你\(n\)个点的坐标\((x,\ y)\)和对应的权值\(w\),让你找到一个矩形,使这个矩阵里面点的权值总和最大. 思路 先离散化纵坐标\(y ...

随机推荐

  1. 【CUDA】CUDA框架介绍

    引用 出自Bookc的博客,链接在此http://bookc.github.io/2014/05/08/my-summery-the-book-cuda-by-example-an-introduct ...

  2. mysql——触发器——前期整理笔记00

    一.触发器 触发器是由事件来出发某个动作.这些事件包括insert语句.update语句和delete语句. 当数据库系统执行这些事件时,就会激活触发器执行相应得动作. 触发器是有insert.upd ...

  3. python 包的概念

    包的概念 包的概念: 在python中包即使模块,是一系列功能的集合体, 为什么要用包? 提高开发效率 如何用包 import ... from ... import ..... 如何认识它就是一包 ...

  4. linux top 查看CPU命令

    top 命令主要用于查看进程的相关信息,同时它也会提供查看系统平均负载,cpu 信息和内存信息 实时监控系统资源使用情况 [root@localhost ~]$ top // 动态查看进程使用资源的情 ...

  5. LayaAir疑难杂症之四:laya引擎自动断点到bundle.js文件中且无报错,但程序不再执行

    在一次断点调试中,突然程序不再按照博主指定的断点执行,莫名其妙端点到了bundle.js文件中的某一行中,这是不应该的,第一次时间反应就是引擎出了问题,但是总不能让博主卸载重装吧. 经过查找资料,询问 ...

  6. hdoj4507(数位dp)

    题目链接:https://vjudge.net/problem/HDU-4507 题意:定义如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关—— 1.整数中某一位是7: 2.整数的每一位 ...

  7. abp.event.on与abp.event.off使用

    apb的全局事件 var eventName = "app.createOrEditFieldModalSaved"; var reloadPage = function () { ...

  8. JackRabbit的来源

    题记 写这系列有点老调重弹的味道,比如ahuaxuan已经在他的博客里对于JackRabbit 1.0做了很详细的阐述.之所以再写,是因为JCR推出了JCR 2.0,个人觉得有必要将一些新的特性再罗列 ...

  9. 几张图让你看懂WebAssembly

    几张图让你看懂WebAssembly:https://www.jianshu.com/p/bff8aa23fe4d

  10. Luogu P2612 [ZJOI2012]波浪

    题目 我们考虑从\(1\)到\(n\)把每个数放到序列里面去,以消掉绝对值. 在最后的序列中,如果\(i\)的某一边是序列的边界,那么\(i\)会产生\(0\)的贡献.如果\(i\)的某一边是一个比\ ...