• SP3266 KQUERY Kquery


    给定一个长度为n的序列a[1]到a[n]

    q次询问:给定i,j,k,求出a[i]到a[j]中大于k的个数

    主席树裸题,但是懒得写

    刚开始写了个莫队+树状数组,复杂度是没问题的\(O(n\sqrt{q}logn)\),但是wa了,也懒得调了

    然后还有种离线做法

    将询问按\(k\)降序排序,对\(a\)降序排序

    我们用一个指针\(l\),如果\(l\)没到头并且\(a[l] > k\),那么就往后移指针,并且把对应位置单点加\(1\),答案就转化为了区间查询和

    因为\(l\)从头到尾最多移一次,所以时间复杂度\(O(nlogn)\)

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    const int N = 3e4;
    const int M = 2e5;
    #define zrt k << 1
    #define yrt k << 1 | 1
    using namespace std;
    struct ad
    {
        int id,v;
    }a[N + 5];
    struct node
    {
        int l,r,k,id;
    }q[M + 5];
    int n,m,ans[M + 5],cnt;
    int cmp1(ad x,ad y)
    {
        return x.v > y.v;
    }
    int cmp2(node x,node y)
    {
        return x.k > y.k;
    }
    struct dd
    {
        int su,tag;
    };
    struct Seg
    {
        dd s[N * 4 + 5];
        void pushup(int k)
        {
            s[k].su = s[zrt].su + s[yrt].su;
        }
        void add(int k,int l,int r,int x,int z)
        {
            if (l == r)
            {
                s[k].su += z;
                return;
            }
            int mid = l + r >> 1;
            if (x <= mid)
                add(zrt,l,mid,x,z);
            else
                add(yrt,mid + 1,r,x,z);
            pushup(k);
        }
        int query(int k,int l,int r,int x,int y)
        {
            if (l >= x && r <= y)
                return s[k].su;
            int mid = l + r >> 1;
            if (x > mid)
                return query(yrt,mid + 1,r,x,y);
            else
                if (y <= mid)
                    return query(zrt,l,mid,x,y);
                else
                    return query(zrt,l,mid,x,y) + query(yrt,mid + 1,r,x,y);
        }
    }tree;
    int main()
    {
        scanf("%d",&n);
        for (int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i].v);
            a[i].id = i;
        }
        scanf("%d",&m);
        for (int i = 1;i <= m;i++)
        {
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
            q[i].id = i;
        }
        sort(a + 1,a + n + 1,cmp1);
        sort(q + 1,q + m + 1,cmp2);
        int l = 1;
        for (int i = 1;i <= m;i++)
        {
            while (l <= n && a[l].v > q[i].k)
            {
                tree.add(1,1,n,a[l].id,1);
                l++;
            }
            ans[q[i].id] = tree.query(1,1,n,q[i].l,q[i].r);
        }
        for (int i = 1;i <= m;i++)
            printf("%d\n",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    结对第一次—原型设计(文献摘要热词统计)
    第一次作业-准备篇
    201771010135杨蓉庆《面向对象程序设计(java)》第二周学习总结
    杨蓉庆201771010135《面向对象程序设计(java)》第一周学习总结
    2019 SDN阅读作业
    第01组 Alpha冲刺 (2/4)
    2019 SDN上机第3次作业
    第01组 ALPHA冲刺(1/4)
    2019SDN上机第二次作业
    2019 SDN上机第1次作业
  • 原文地址:https://www.cnblogs.com/sdlang/p/13067964.html
Copyright © 2020-2023  润新知