原题链接:http://codeforces.com/problemset/problem/853/C
对于一个矩形,可以把整个平面划分为9块区域。然后只要暴力枚举各块区域进行配对就可以得到答案。
同时用树状数组求各个区域内的格子数。
代码:
#include <bits/stdc++.h>
using namespace std;
inline void read(int &x){
char ch;
bool flag=false;
for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
x=flag?-x:x;
}
inline void read(long long &x){
char ch;
bool flag=false;
for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
x=flag?-x:x;
}
inline void write(int x){
static const int maxlen=100;
static char s[maxlen];
if (x<0) { putchar('-'); x=-x;}
if(!x){ putchar('0'); return; }
int len=0; for(;x;x/=10) s[len++]=x % 10+'0';
for(int i=len-1;i>=0;--i) putchar(s[i]);
}
const int MAXN = 410000;
const int MAXQ = 410000;
struct Check_Point{
int x,y;
int id;
int sum;
Check_Point(){}
Check_Point(int x,int y,int id ):x(x),y(y),id(id){}
}point [5][ MAXQ ];
int n , m;
int a[ MAXN ];
int x[4][MAXN];
int y[4][MAXN];
int sum[ MAXN ];
int lowbit(int x){
return x&(-x);
}
void add(int x){
while (x<=n)
{
sum[x]++;
x+=lowbit(x);
}
}
int get_sum(int x){
int tmp=0;
while (x)
{
tmp+=sum[x];
x-=lowbit(x);
}
return tmp;
}
bool cmp_x( Check_Point A ,Check_Point B ){
return A.x<B.x;
}
bool cmp_id( Check_Point A ,Check_Point B ){
return A.id<B.id;
}
void doit( Check_Point point[] ){
sort( point+1, point+m+1 , cmp_x );
memset( sum , 0 , sizeof( sum ) );
int now=1;
for (int i=1;i<=m;i++)
{
int r=i;
while ( ( r< m ) && ( point[ r+1 ].x == point[ i ].x ) )
r++;
while ( (now<=n ) && ( now< point [ i ].x ) )
add( a[now++] );
for (int j=i;j<=r;j++)
point[j].sum = get_sum( point[j].y-1 );
i=r;
}
}
int tmp[5][5];
int main(){
read(n); read(m);
for (int i=1;i<=n;i++)
read(a[i]);
for (int i=1;i<=m;i++)
{
int a,b,c,d;
read(a); read(b); read(c); read(d);
x[1][i]=a; x[2][i]=c;
y[1][i]=b; y[2][i]=d;
point[1][i] = Check_Point( a , b , i );
point[2][i] = Check_Point( a , n+1-d , i );
point[3][i] = Check_Point( n+1-c , b , i );
point[4][i] = Check_Point( n+1-c , n+1-d , i );
}
doit( point[1] );
for (int i=1;i<=n;i++)
a[i]=n+1-a[i];
doit( point[2] );
reverse( a+1 , a+n+1 );
doit( point[4] );
for (int i=1;i<=n;i++)
a[i]=n+1-a[i];
doit( point[3] );
for (int i=1;i<=4;i++)
sort( point[i]+1, point[i]+1+m , cmp_id );
for (int i=1;i<=m;i++)
{
long long ans=0;
tmp[1][1] = point[1][i].sum;
tmp[3][1] = point[3][i].sum;
tmp[1][3] = point[2][i].sum;
tmp[3][3] = point[4][i].sum;
tmp[1][2] = x[1][i] - tmp[1][1] - tmp[1][3]-1;
tmp[2][1] = y[1][i] - tmp[1][1] - tmp[3][1]-1;
tmp[2][3] = n - y[2][i] - tmp[1][3] - tmp[3][3];
tmp[3][2] = n - x[2][i] - tmp[3][1] - tmp[3][3];
tmp[2][2] = x[2][i] - x[1][i] +1 -tmp[2][1]-tmp[2][3];
ans+=1ll*tmp[1][1]*(tmp[2][2]+tmp[2][3]+tmp[3][2]+tmp[3][3]);
ans+=1ll*tmp[1][2]*(n-x[1][i]+1);
ans+=1ll*tmp[1][3]*(tmp[2][2]+tmp[2][1]+tmp[3][2]+tmp[3][1]);
ans+=1ll*tmp[2][1]*(tmp[2][2]+tmp[2][3]+tmp[3][2]+tmp[3][3]);
ans+=1ll*tmp[2][2]*(tmp[2][3]+tmp[3][1]+tmp[3][2]+tmp[3][3]);
ans+=1ll*tmp[2][3]*(tmp[3][1]+tmp[3][2]);
ans+=1ll*tmp[2][2]*(tmp[2][2]-1)/2ll;
/*
for (int j=3;j>=1;j--)
{
for (int k=1;k<=3;k++)
printf("%d ",tmp[k][j]);
puts("");
}
*/
printf("%I64d\n",ans);
}
return 0;
}