• BZOJ3236: [Ahoi2013]作业


    【传送门:BZOJ3236


    简要题意:

      给出一个n个数的序列,序列中的数范围为1到n,给出m个操作,每个操作输入l,r,a,b,输出l到r中权值为a到b的数的个数和l到r中权值为a到b的数的种类


    题解:

      BZOJ3809的添加版,其实差不多

      只是在BZOJ3809的做法上多加一个求个数和的数组就可以了


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct node
    {
        int l,r,a,b,id,d1,d2;
    }q[1100000];
    int s[110000];
    int bl[1100],br[1100],belong[110000];
    bool cmp1(node n1,node n2)
    {
        if(belong[n1.l]<belong[n2.l]) return true;
        if(belong[n1.l]>belong[n2.l]) return false;
        if(belong[n1.l]==belong[n2.l])
        {
            if(n1.r<n2.r) return true;
            if(n1.r>n2.r) return false;
        }
        return false;
    }
    bool cmp2(node n1,node n2)
    {
        return n1.id<n2.id;
    }
    int d1[1100],d2[1100],sum[110000];
    void add(int x)
    {
        sum[x]++;d2[belong[x]]++;
        if(sum[x]==1) d1[belong[x]]++;
    }
    void del(int x)
    {
        sum[x]--;d2[belong[x]]--;
        if(sum[x]==0) d1[belong[x]]--;
    }
    int solve1(int x,int y)
    {
        int bx=belong[x],by=belong[y];
        int ans=0;
        if(bx==by)
        {
            for(int i=x;i<=y;i++)
            {
                if(sum[i]>0) ans++;
            }
            return ans;
        }
        for(int i=bx+1;i<=by-1;i++) ans+=d1[i];
        for(int i=x;i<=br[bx];i++) if(sum[i]>0) ans++;
        for(int i=bl[by];i<=y;i++) if(sum[i]>0) ans++;
        return ans;
    }
    int solve2(int x,int y)
    {
        int bx=belong[x],by=belong[y];
        int ans=0;
        if(bx==by)
        {
            for(int i=x;i<=y;i++) ans+=sum[i];
            return ans;
        }
        for(int i=bx+1;i<=by-1;i++) ans+=d2[i];
        for(int i=x;i<=br[bx];i++) ans+=sum[i];
        for(int i=bl[by];i<=y;i++) ans+=sum[i];
        return ans;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&s[i]);
        int block=int(sqrt(n));
        for(int i=1;i<=n;i++)
        {
            int t=(i-1)/block+1;
            belong[i]=t;
            if(bl[t]==0) br[t-1]=i-1,bl[t]=i;
        }
        br[belong[n]]=n;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].a,&q[i].b);
            q[i].id=i;
        }
        sort(q+1,q+m+1,cmp1);
        memset(sum,0,sizeof(sum));
        memset(d1,0,sizeof(d1));
        memset(d2,0,sizeof(d2));
        int l=1,r=0;
        for(int i=1;i<=m;i++)
        {
            while(l>q[i].l){l--;add(s[l]);}
            while(l<q[i].l){del(s[l]);l++;}
            while(r>q[i].r){del(s[r]);r--;}
            while(r<q[i].r){r++;add(s[r]);}
            q[i].d1=solve1(q[i].a,q[i].b);
            q[i].d2=solve2(q[i].a,q[i].b);
        }
        sort(q+1,q+m+1,cmp2);
        for(int i=1;i<=m;i++) printf("%d %d
    ",q[i].d2,q[i].d1);
        return 0;
    }

     

  • 相关阅读:
    HDU 3549 基础网络流EK算法 Flow Problem
    HDU 1937 F
    HDU 1937 J
    HDU 1939 HE IS OFFSIDE
    HDU 3033 组合背包变形 I love sneakers!
    分组背包
    hdu1712 分组背包 ACboy needs your help
    hdu 1714 RedField
    HDU 1709 母函数天平问题 可出现减法的情况 The Balance
    HDU 1171 Big Event in HDU 母函数
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8514019.html
Copyright © 2020-2023  润新知