zoukankan      html  css  js  c++  java
  • bzoj3809:Gty的二逼妹子序列

    【题目描述】

    Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。

    对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。

    为了方便,我们规定妹子们的美丽度全都在[1,n]中。

    给定一个长度为n(1≤n≤100000)的正整数序列s(1≤si≤n),对于m(1≤m≤1000000)次询问“l,r,a,b”,每次输出sl...sr中,权值∈[a,b]的权值的种类数。

    【输入】

    第一行包括两个整数n,m(1≤n≤100000,1≤m≤1000000),表示数列s中的元素数和询问数。

    第二行包括n个整数s1...sn(1≤si≤n)。

    接下来m行,每行包括4个整数l,r,a,b(1≤l≤r≤n,1≤a≤b≤n),意义见题目描述。

    保证涉及的所有数在C++的int内。

    保证输入合法。

    【输出】

    对每个询问,单独输出一行,表示sl...sr中权值∈[a,b]的权值的种类数。

    【输入样例】

    10 10
    4 4 5 1 4 1 5 1 2 1
    5 9 1 2
    3 4 7 9
    4 4 2 5
    2 3 4 7
    5 10 4 4
    3 9 1 1
    1 4 5 9
    8 9 3 3
    2 2 1 6
    8 9 1 4
    

    【输出样例】

    2
    0
    0
    2
    1
    1
    1
    0
    1
    2
    

    【提示】

    v>样例的部分解释:

    5 9 1 2

    子序列为4 1 5 1 2

    在[1,2]里的权值有1,1,2,有2种,因此答案为2。

    3 4 7 9

    子序列为5 1

    在[7,9]里的权值有5,有1种,因此答案为1。

    4 4 2 5

    子序列为1

    没有权值在[2,5]中的,因此答案为0。

    2 3 4 7

    子序列为4 5

    权值在[4,7]中的有4,5,因此答案为2。

    建议使用输入/输出优化。

    题解:

    莫队,将询问以左端点所处块的位置为第一关键字,右端点位置为第二关键字排序,保证对于左端点在同一块内的所有询问,其右端点单增

    然后对权值分块,即可O(1)修改,O(sqrt(n))查询

    #include<bits/stdc++.h>
    #define MAXN 100005
    using namespace std;
    struct qz{
        int l,r,al,br,num;
    }q[1000005];
    int n,m,sz;
    int arr[MAXN],idx[MAXN],blo[320],cnt[MAXN],ans[1000005];
    inline int read()
    {
        int X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    inline void write(int x)
    {
         if(x<0) putchar('-'),x=-x;
         if(x>9) write(x/10);
         putchar(x%10+'0');
    }
    inline bool cmp(qz a1,qz b1)
    {
        if(idx[a1.l]<idx[b1.l])
           return true;
        if(idx[a1.l]==idx[b1.l])
           if(a1.r<b1.r)
              return true;
        return false;       
    }
    inline int query(int ll,int rr)
    {
        int ret=0;
        if(idx[ll]==idx[rr])
           {
                  for(register int i=ll;i<=rr;i++)
                      if(cnt[i]!=0)
                         ret++;
                  return ret;       
           }
        if(ll==(idx[ll]-1)*sz+1&&rr==idx[rr]*sz)
           {
                  for(register int i=idx[ll];i<=idx[rr];i++)
                      ret+=blo[i];
                  return ret;    
           }      
        int lx=idx[ll]*sz,rx=(idx[rr]-1)*sz+1;
        for(register int i=ll;i<=lx;i++)
            if(cnt[i]!=0)
               ret++;
        for(register int i=rx;i<=rr;i++)
            if(cnt[i]!=0)
               ret++;
        lx=idx[ll]+1;
        rx=idx[rr]-1;       
        for(register int i=lx;i<=rx;i++)
            ret+=blo[i];
        return ret;            
    }
    inline void del(int p)
    {
        cnt[p]--;
        if(cnt[p]==0)
           blo[idx[p]]--;
    }
    inline void add(int p)
    {
        cnt[p]++;
        if(cnt[p]==1)
           blo[idx[p]]++;
    }
    int main()
    {
        n=read();m=read();
        sz=(int)sqrt(n);
        for(register int i=1;i<=n;i++)
            idx[i]=(i-1)/sz+1;
        for(register int i=1;i<=n;i++)
            arr[i]=read();
        for(register int i=1;i<=m;i++)
            {
                q[i].num=i;
                q[i].l=read();q[i].r=read();q[i].al=read();q[i].br=read();
            }
        sort(q+1,q+1+m,cmp);
        int L=1,R=0;
        for(register int i=1;i<=m;i++)
            {
                while(L<q[i].l)
                      {
                           del(arr[L]);
                           L++;
                      }
                while(R>q[i].r)
                      {
                            del(arr[R]);
                            R--;
                      }                  
                while(L>q[i].l)
                      {
                            L--;
                            add(arr[L]);
                      }
                while(R<q[i].r)
                      {
                            R++;
                            add(arr[R]);
                      }  
                ans[q[i].num]=query(q[i].al,q[i].br);                             
            }
        for(register int i=1;i<=m;i++)
            {
                write(ans[i]);
                printf("
    ");
            }
        return 0;
    }
    View Code
  • 相关阅读:
    使用poi读写excel文件
    视频云全球创新挑战赛 — 视频目标分割经典算法解析
    阿里云 RTC QoS 弱网对抗之变分辨率编码
    用 WebRTC 打造一个音乐教育 App,要解决哪些音质难题?
    “蚂蚁呀嘿” 刷屏的背后:算法工程师带你理性解构神曲
    白话解读 WebRTC 音频 NetEQ 及优化实践
    未来直播 “神器”,像素级视频分割是如何实现的 | CVPR 冠军技术解读
    「 视频云大赛 — 大咖驾到 」驱动下一代技术浪潮,我们更专注价值落地
    「 视频云大赛 — 大咖驾到 」下一代技术新浪潮,正由视频云驱动
    视频云大赛|视频目标分割,下一个视频算法技术爆发点?
  • 原文地址:https://www.cnblogs.com/nanjolno/p/9348413.html
Copyright © 2011-2022 走看看