zoukankan      html  css  js  c++  java
  • Different Integers

    牛客一 J题 树状数组

    题目描述

    Given a sequence of integers a1, a2, ..., an and q pairs of integers (l1, r1), (l2, r2), ..., (lq, rq), find count(l1, r1), count(l2, r2), ..., count(lq, rq) where count(i, j) is the number of different integers among a1, a2, ..., ai, aj, aj + 1, ..., an.

    输入描述:

    The input consists of several test cases and is terminated by end-of-file.
    The first line of each test cases contains two integers n and q.
    The second line contains n integers a1, a2, ..., an.
    The i-th of the following q lines contains two integers li and ri.

    输出描述:

    For each test case, print q integers which denote the result.

    示例

    输入

    3 2
    1 2 1
    1 2
    1 3
    4 1
    1 2 3 4
    1 3

    输出

    2
    1
    3

    备注:

    • 1 ≤ n, q ≤ 105
    • 1 ≤ ai ≤ n
    • 1 ≤ li, ri ≤ n
    • The number of test cases does not exceed 10.

    题解

    这场比赛的签到题 有很多种方法:莫队,主席树等 不过我不会

    标程是树状数组,树状数组可以对区间进行跳跃性的操作。首先是题意,题意要求我们找[0,l]与[r,n]两个区间加起来不同的数,我看到标程将数组扩大一倍,就相当于找[r,l]区间不同的数,不过我觉得没有这个必要。
    首先把那三个函数写好,套模板
    我们可以标记每个数字出现的前后位置,当遍历到一个数的最后一个数字后,从这个数开始的位置向上更新,这样可以快速更新这个位置之前有多少种数,(l前有多少种数并且结束的-r前有多少开始并结束的)=空缺区间有多少种数开始并已经结束,然后总的减去这个数就可以
    下面是在百度辛苦折腾下终于AC的代码

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 5;
    struct node
    {
        int l,r,num;
    }f[maxn];
    int s[maxn];
    int pre[maxn];
    int las[maxn];
    int ans[maxn];
    int tree[maxn];
    int n;
    bool cmp(node a,node b)
    {
        return a.r<b.r;
    }
    /* 树状数组函数模板*/
    void add(int i, int v) {
        while(i <= n+1) {
            tree[i] += v;
            i += i&-i;
        }
    }
    
    int query(int i) {
        int ret = 0;
        while(i) {
            ret += tree[i];
            i -= i&-i;
        }
        return ret;
    }
    /*******************/
    int main() {
       int q;
       int tot=0;
       while(scanf("%d%d",&n,&q)!=EOF){
            memset(pre,0,sizeof(pre));
            memset(tree,0,sizeof(tree));
            memset(las,0,sizeof(las));
            tot=0;
           for(int i=1;i<=n;i++){
            scanf("%d",&s[i]);
            if(!pre[s[i]]){
                tot++;
                pre[s[i]]=i;
            }
            las[s[i]]=i;
           }
           for(int i=1;i<=q;i++){
            scanf("%d %d",&f[i].l,&f[i].r);
            f[i].num=i;
           }
           int nowl=1;
           sort(f+1,f+1+q,cmp);
           for(int i=1;i<=n;i++){
            while(nowl<=q&&f[nowl].r==i){
                int num=f[nowl].num;
                ans[num]=tot-(query(f[nowl].r)-query(f[nowl].l));
                nowl++;
    
            }
            if(las[s[i]]==i) add(pre[s[i]],1);
           }
           for(int i=1;i<=q;i++) printf("%d
    ",ans[i]);
       }
    }
    
    
    不要忘记努力,不要辜负自己 欢迎指正 QQ:1468580561
  • 相关阅读:
    apply 和 call 方法详解【转载】
    npm无法安装node-sass的解决方法
    rem
    创建和存储 cookie
    webpack学习(一):webpack的安装和命令行
    gulp常用的插件
    移动前端开发之viewport的深入理解
    JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序
    JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue
    JavaSE中Collection集合框架学习笔记(1)——具有索引的List
  • 原文地址:https://www.cnblogs.com/smallocean/p/9363588.html
Copyright © 2011-2022 走看看