WHU 1551 Pairs(分块暴力)

来源:互联网 发布:巨人网络私有化进程 编辑:程序博客网 时间:2024/04/29 14:49
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
Hint
题意:给你N个数,M次询问,每次询问求区间[L,R]的符合|ai-aj|<=2&&i<j的个数
分析:我们考虑加入一个数u对个数的影响,加入一个u后,那么增加的个数就是cnt[u]+cnt[u-1]+cnt[u-2]
+cnt[u+1]+cnt[u+2],删除一个u后,减少的个数就是cnt[u]+cnt[u-1]+cnt[u-2]+cnt[u+1]+cnt[u+2].
每次操作将cnt[u]的个数更新。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;const int maxn=1e5+10;int n,m,sum;int c[maxn],pos[maxn];int num[maxn],ans[maxn];struct node{    int l,r;    int id;}q[maxn];int cmp(node l1,node l2){    if(pos[l1.l]==pos[l2.l])        return l1.r<l2.r;    return l1.l<l2.l;}void Add(int i){    int val=c[i];    int temp=num[val-1]+num[val-2]+num[val+1]+num[val+2];    temp+=num[val];    sum+=temp;  num[val]++;}void Sub(int i){    int val=c[i];    int temp=num[val-1]+num[val-2]+num[val+1]+num[val+2];    temp+=num[val];    sum-=temp-1;  num[val]--;}int main(){    int l,r;    int cas=1;    while(~scanf("%d%d",&n,&m))    {        int block=(int)sqrt(n*1.0+0.5);        CLEAR(num,0);        REPF(i,1,n)        {            scanf("%d",&c[i]);            c[i]+=1;            pos[i]=(i-1)/block+1;        }        REP(i,m)        {            scanf("%d%d",&l,&r);            q[i].l=l;q[i].r=r;            q[i].id=i;        }        sort(q,q+m,cmp);        sum=0;        int L=1,R=0;        for(int i=0;i<m;i++)        {            while(L>q[i].l) Add(--L);            while(R<q[i].r) Add(++R);            while(L<q[i].l) Sub(L++);            while(R>q[i].r) Sub(R--);            ans[q[i].id]=sum;        }        printf("Case %d:\n",cas++);        for(int i=0;i<m;i++)            printf("%d\n",ans[i]);    }    return 0;}/*10 15 5 1 3 6 3 5 7 1 73 4*/


0 0