题意:
n*n的矩阵,有n个不同行列的格子染色,染色的格子两两之间组成的矩阵定义为beautiful。
q组询问,每次给出一个矩阵,询问与它相交的beautiful的矩阵的数目
n,q<=2e5
思路:
每次查询分成九个矩阵,只需要知道各个矩阵中的染色的点数,即可得出答案
其中五个矩阵可以由染色的性质可以直接得出答案
离线处理另外四个即可
代码:
#include<bits/stdc++.h>
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define fi first
#define se second
#define LL long long
const int N = 2e5+10;
using namespace std;
int n,q;
int num[N][9];
struct node{
int x,y,pos;
}Q[N<<2];
int bit[1<<20];
pii P[N];
inline LL C2(int x){return 1LL * x * (x-1) / 2 ;}
void add(int x){
while(x<=n){
++bit[x];
x+=lowbit(x);
}
}
int query(int x){
int res = 0;
while(x){
res += bit[x];
x -= lowbit(x);
}return res;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1,x;i<=n;++i){
scanf("%d",&x);
P[i-1] = pii(i,x);
}for(int i=0,l,d,r,u,j=0,k;i<q;i++){
k = i*9;
scanf("%d%d%d%d",&l,&d,&r,&u);--l;--d;
Q[j++] = node{l,d,k};
Q[j++] = node{r,d,k+1};
Q[j++] = node{l,u,k+3};
Q[j++] = node{r,u,k+4};
num[i][6] = l;num[i][7] = r;
num[i][2] = d;num[i][5] = u;
num[i][8] = n;
}q <<= 2;
sort(Q,Q+q,[](node a,node b){return a.x<b.x;});
int p = 0;
for(int i=0;i<q;++i){
while(p<n&&P[p].fi<=Q[i].x)add(P[p++].se);
num[Q[i].pos/9][Q[i].pos%9] = query(Q[i].y) ;
}q >>= 2;LL sum = C2(n);
for(int i=0;i<q;++i){
LL ans = sum - C2(num[i][2]) - C2(num[i][6]) - C2(num[i][8]-num[i][7]) - C2(num[i][8]-num[i][5]);
num[i][5] -= num[i][4] ;
num[i][8] -= num[i][7] + num[i][5];
ans += C2(num[i][0]) + C2(num[i][6]-num[i][3]) + C2(num[i][2]-num[i][1]) + C2(num[i][8]);
printf("%I64d\n",ans);
}
return 0;
}