• [AHOI2013] 作业


    Description

    给定一个长度为 (n) 的数列,每个数都在 ([1,10^5]) 范围内。有 (m) 个询问,每次给定 (l,r,a,b),求下标在 ([l,r]) 中,值在 ([a,b]) 范围内的数构成的多重集和普通集合,大小分别为多少。

    Solution

    莫队,树状数组维护。

    设块大小为 (k),则复杂度为 (O(n(k+frac n k) log n)),于是 (k=sqrt n),复杂度为 (O(nsqrt n log n))

    如果需要追求更优复杂度可以考虑值域分块代替树状数组,由于询问次数远小于修改次数(需要稍作修改),故可以考虑值域分块来做到 (O(1)) 修改,(O(sqrt n)) 询问。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 100005;
    
    struct BIT
    {
        int ar[N];
        int lowbit(int t)
        {
            return t & (-t);
        }
        void add(int i, int v)
        {
            for (; i < N; ar[i] += v, i += lowbit(i));
        }
        int sum(int i)
        {
            int s = 0;
            for (; i > 0; s += ar[i], i -= lowbit(i));
            return s;
        }
        int query(int i,int j)
        {
            return sum(j)-sum(i-1);
        }
    } a,b;
    
    int c[N],n,m;
    int k,bel[N],a1[N],a2[N];
    
    struct Query
    {
        int l,r,a,b,id;
        bool operator < (const Query &x)
        {
            if(bel[l]!=bel[x.l]) return bel[l]<bel[x.l];
            else return r<x.r;
        }
    } q[N];
    
    namespace Range
    {
        int l=1,r=0;
        void add(int x)
        {
            a.add(x,1);
            if(b.query(x,x)==0) b.add(x,1);
        }
        void dec(int x)
        {
            if(a.query(x,x)==1) b.add(x,-1);
            a.add(x,-1);
        }
        void ladd()
        {
            --l;
            add(c[l]);
        }
        void radd()
        {
            ++r;
            add(c[r]);
        }
        void ldec()
        {
            dec(c[l]);
            ++l;
        }
        void rdec()
        {
            dec(c[r]);
            --r;
        }
        void adjust(int ql,int qr)
        {
            while(ql<l) ladd();
            while(qr>r) radd();
            while(l<ql) ldec();
            while(r>qr) rdec();
        }
        int getans1(int l,int r)
        {
            return a.query(l,r);
        }
        int getans2(int l,int r)
        {
            return b.query(l,r);
        }
    }
    
    using Range::adjust;
    using Range::getans1;
    using Range::getans2;
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1; i<=n; i++) cin>>c[i];
        k=sqrt(n);
        for(int i=1; i<=n; i++) bel[i]=(i-1)/k+1;
        for(int i=1; i<=m; i++)
        {
            cin>>q[i].l>>q[i].r>>q[i].a>>q[i].b;
            q[i].id=i;
        }
        sort(q+1,q+m+1);
        for(int i=1; i<=m; i++)
        {
            adjust(q[i].l,q[i].r);
            a1[q[i].id]=getans1(q[i].a,q[i].b);
            a2[q[i].id]=getans2(q[i].a,q[i].b);
        }
        for(int i=1; i<=m; i++)
        {
            cout<<a1[i]<<" "<<a2[i]<<endl;
        }
    }
    
    
    
  • 相关阅读:
    docker安装 与 基本配置
    linux 挂载windows ntfs 分区 -- centos 安装ntfs-3g
    Linux find 用法示例
    linux之sed用法
    js -ajax 学习
    搭建SSH框架整合Struts2和Spring时,使用@Autowired注解无法自动注入
    Hibernate学习之属性级别注解
    Hibernate学习之类级别注解
    org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    Hibernate学习之二级缓存
  • 原文地址:https://www.cnblogs.com/mollnn/p/13061352.html
Copyright © 2020-2023  润新知