zoto(莫队+分块)

题目:

Problem Description

You are given an array fx.
For each i(1<=i<=n) , we use a point (i,fx[i]) in XoY coordinate plane to described it.
You are asked to answer m queries, in each query there will be a rectangle and you need to count how many
different y-cooordinate (of the points mentioned above) in the queried rectangle.
 

Input

The first line contains an integer T(1<=T<=5) representing the number of test cases.
For each test case , there are two integers n,m(1<=n<=100000,1<=m<=100000) in the first line.
Then one line contains n integers fx[i](0<=fx[i]<=100000)
Each of the next m lines contain four integers x0,y0,x1,y1(1<=x0<=x1<=n,0<=y0<=y1<=100000) which means matrix's lower-leftmost
cell is (x0,y0) and upper-rightest cell is (x1,y1).

Output

For each test case print a single integer in a new line.
 
Sample Input
1
4 2
1 0 3 1
1 0 4 3
1 0 4 2
Sample Output
3 2
 

题解

由于只有询问操作,自然想到用莫队来离线处理X轴的移动,关键在于Y点数的维护,Y 轴的区间分块处理

这个分块核心,就是块中部分不用一个一个求了,块中+块外

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5e5+100;
int cnt[maxn],sum[maxn],block=313;
int a[maxn],pos[maxn],ans[maxn];
struct node{
    int l,r,ma,mi,id;
}q[maxn];
bool cmp(node x,node y){
    if(x.l/block!=y.l/block){
        return x.l/block<y.l/block;
    }
    else{
        if((x.l/block)&1){
            return x.r>y.r;
        }
        else{
            return x.r<y.r;
        }
    }
}
void add(int x){
    cnt[x]++;
    if(cnt[x]==1){
        sum[x/block]++;//先把每一个块中加上
    }
}
void del(int x){
    cnt[x]--;
    if(cnt[x]==0){
        sum[x/block]--;
    }
}
int cal(int x){
    int ans=0;
    for(int i=0;i<x/block;i++){//先求块中的部分,这是分块的核心
        ans+=sum[i]; 
    } 
    for(int i=(x/block)*block;i<=x;i++){//除了块中部分,剩余的部分
        ans+=(cnt[i]>=1);
    }
    return ans;
} 
int main(){
    int t;    
    scanf("%d",&t);
    while(t--){
        memset(sum,0,sizeof(sum));
        memset(cnt,0,sizeof(cnt));
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d%d",&q[i].l,&q[i].mi,&q[i].r,&q[i].ma);
            q[i].id=i;
        }
        sort(q+1,q+m+1,cmp);
        int ql=q[1].l,qr=q[1].r;
        for(int i=ql;i<=qr;i++){
            add(a[i]);
        }
        ans[q[1].id]=cal(q[1].ma)-cal(q[1].mi-1);
        for(int i=2;i<=m;i++){
            while(ql<q[i].l){
                del(a[ql]);
                ql++;
            } 
            while(qr>q[i].r){
                del(a[qr]);
                qr--;
            }
            while(ql>q[i].l){
                ql--;
                add(a[ql]);
            }
            while(qr<q[i].r){
                qr++;
                add(a[qr]);
            }
            ans[q[i].id]=cal(q[i].ma)-cal(q[i].mi-1); 
        }
        for(int i=1;i<=m;i++){
            printf("%d\n",ans[i]);
        }
    }    
} 

 

posted @ 2021-07-27 21:19  lipu123  阅读(103)  评论(0)    收藏  举报