• WHU-1551-Pairs(莫队算法+分块实现)


    Description

     Give you a sequence consisted of n numbers. You are required to answer how many pairs of numbers (ai, aj) satisfy that | ai - aj | <= 2 and L <= i < j <= R.

    Input
    The input consists of one or more test cases.

    For each case, the first line contains two numbers n and m, which represent the length of the number sequence and the number of queries. ( 1 <= n <= 10^5 and 1 <= m <= 10^5 )
    The second line consists of n numbers separated by n - 1 spaces.( 0 <= ai <= 10^5 )
    Then the m lines followed each contain two values Li and Ri.
    Output
    For each case, first output “Case #: “ in a single line, where # will be replaced by case number.
    Then just output the answers in m lines.
    Sample Input
    10 10
    5 5 1 3 6 3 5 7 1 7
    3 4
    6 8
    8 9
    2 8
    5 7
    6 7
    1 9
    3 10
    3 10
    5 6
    Sample Output
    Case 1:
    1
    2
    0
    13
    2
    1
    22
    14
    14
    0


    思路:把n个数分成 sqrt(n)块。用pos数组保存i所在的块。将全部查询按(pos(l),r)双keyword排序(这样子是为了降低后面的移动次数),然后模拟l向左向右移,r向左向右移,求出全部区间的结果。详见代码。


    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    struct Q{
    int l,r,index,ans;
    }query[100001];
    
    int pos[100001],f[100001],w[100001];
    
    bool cmplr(struct Q a,struct Q b)
    {
        if(pos[a.l]==pos[b.l]) return a.r<b.r;//先按l所在的块排。假设相等就按r排
        else return pos[a.l]<pos[b.l];
    }
    
    bool cmpid(struct Q a,struct Q b)
    {
        return a.index<b.index;
    }
    
    int update(int p,int ans,int add)//每移一步就更新一次结果
    {
        int i;
    
        if(add==1)//1代表区间长度加1
        {
            for(i=w[p]-2;i<=w[p]+2;i++)
            {
                if(i>=0) ans+=f[i];
            }
            f[w[p]]++;//f[i]表示当前区间里面包括了f[i]个i
        }
        else//-1代表区间长度减1
        {
            f[w[p]]--;//f[i]表示当前区间里面包括了f[i]个i
            for(i=w[p]-2;i<=w[p]+2;i++)
            {
                if(i>=0) ans-=f[i];
            }
        }
    
        return ans;
    }
    
    int main()
    {
        int n,m,cnt,i,ans,l,r,casenum=1;
    
        while(~scanf("%d%d",&n,&m))
        {
            memset(f,0,sizeof(f));//f[i]表示当前区间里面包括了f[i]个i
    
            cnt=(int)sqrt(n);//分成sqrt(n)块
    
            for(i=1;i<=n;i++)
            {
                scanf("%d",&w[i]);
                pos[i]=i/cnt;
            }
    
            for(i=1;i<=m;i++)
            {
                scanf("%d%d",&query[i].l,&query[i].r);
                query[i].index=i;
            }
    
            sort(query+1,query+m+1,cmplr);
    
            ans=0;
            l=1,r=0;
            for(i=1;i<=m;i++)//每一次都使l和r指向查询区间的l和r,这样子区间长度添加时就不用把自己加进去了,区间长度减小时要把自己减去
            {
                if(query[i].l==query[i].r)
                {
                    query[i].ans=0;
                    continue;
                }
    
                if(r<query[i].r)
                {
                    for(r=r+1;r<=query[i].r;r++)
                    {
                        ans=update(r,ans,1);
                    }
                    r--;
                }
                if(r>query[i].r)
                {
                    for(;r>query[i].r;r--)
                    {
                        ans=update(r,ans,-1);
                    }
                }
                if(l<query[i].l)
                {
                    for(;l<query[i].l;l++)
                    {
                        ans=update(l,ans,-1);
                    }
                }
                if(l>query[i].l)
                {
                    for(l=l-1;l>=query[i].l;l--)
                    {
                        ans=update(l,ans,1);
                    }
                    l++;
                }
    
                query[i].ans=ans;
                //printf("index=%d,l=%d,r=%d,ans=%d
    ",query[i].index,query[i].l,query[i].r,query[i].ans);
            }
    
            sort(query+1,query+m+1,cmpid);
    
            printf("Case %d:
    ",casenum++);
    
            for(i=1;i<=m;i++)
            {
                printf("%d
    ",query[i].ans);
            }
        }
    
    }
    


  • 相关阅读:
    myEclipse,web项目连接数据库
    jquery模拟手机短信发送
    myEclipse创建web项目及运行
    总结SUMMARY
    pthread
    NSThread线程对象
    刀哥多线程自动释放池autoreleasepool
    仿SDWebImage
    多线程基本概论multithread
    多线程异步加载图片async_pictures
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6876811.html
Copyright © 2020-2023  润新知