题意 : 给出一段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. mapper中通过resultMap自定义查询结果映射

    mybatis中使用resultType做自动映射时,要注意字段名和pojo的属性名必须一致,若不一致,则需要给字段起别名,保证别名与属性名一致. 使用resultMap做自定义结果映射,字段名可以不 ...

  2. stack的常见用法

    stack的常见用法 栈是什么? 栈是一种先进后出的容器 栈的定义 引入头文件 # include <stack> using namespace std; 定义栈 可以定义任何类型的栈 ...

  3. 带EFI支持的GRUB2安装全记录

    版权归作者所有,任何形式转载请联系作者. 作者:keenshoes(来自豆瓣) 来源:https://www.douban.com/note/210077866/  关键词:EFIGRUB2efibo ...

  4. Codeforces893F_Subtree Minimum Query

    题意 给定一棵树和根,每个点有点权,强制在线询问\(x\)子树里离\(x\)距离不超过\(k\)的最小点权. 分析 权值线段树合并的套路题,dfs,以深度作为下标,点权作为值,对每个点建立一颗权值线段 ...

  5. allure 这么高大上的测试报告环境,5 分钟搞定

    allure 的测试报告是老板喜欢的样子.如果能用上 allure,干嘛还选择其他的测试报告类型呢?python 的 pytest 单元测试框架有 allure 的插件,可以很方便的在 python ...

  6. tf.get_variable函数的使用

    tf.get_variable(name,  shape, initializer): name就是变量的名称,shape是变量的维度,initializer是变量初始化的方式,初始化的方式有以下几种 ...

  7. Vue Cli 移动端开发

    一.

  8. PAT Advanced 1048 Find Coins (25 分)

    Eva loves to collect coins from all over the universe, including some other planets like Mars. One d ...

  9. 洛谷P1412 经营与开发题解

    题目链接QWQ这里就不阐述了: 题解部分: 从题面上来看,这是个dp(递推)的题目. 但是dp要满足无后效性,但这个题为了取最值,得考虑从当前开始一直持续到结束的p的影响. 这让我们怎么满足无后效性? ...

  10. parted分区的步骤

    使用parted分区的步骤1. fdisk -l             ##查看一下当前的存储设备,这里可以看到新加入的磁盘,比如/dev/sdb2. parted /dev/sdb         ...