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
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
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]); } } }