题目链接:Codeforces Round #433 (Div. 2) E. Boredom
题意:
在一个n*n的二维平面上,有n个标记,每列只有一个标记。
现在定义美丽的矩形为以两个标记所在位置构成的矩形。
现在有q个询问,每次询问一个矩形,问有多少个美丽的矩形与询问的矩形相交。
题解:
先用建一棵主席树用于查询二维平面的标记的个数。
然后对于每个询问,将平面分为了9个部分(9宫格)。
1 2 3
4 5 6
7 8 9
中间那个5就是询问的矩形。
定义i为第i部分的标记个数。
现在答案就是
ans=(1*(6+8+9)+2*(4+6+7+8+9)+3*(4+7+8)+4*(2+3+6+8+9)+6*(1+2+4+7+8)+7*(2+3+6)+8*(1+2+3+4+6)+9*(1+2+4))/2+(1+2+3+4+6+7+8+9)*5+5*5/2
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 typedef long long ll; 5 6 const int N=2e5+7; 7 struct Node{int l,r,sum;}T[N*40]; 8 int n,q,cnt,x,root[N]; 9 ll pre[N]; 10 11 void update(int &x,int y,int pos,int l=1,int r=n) 12 { 13 T[x=++cnt]=T[y],T[x].sum++; 14 if(l==r)return; 15 int mid=l+r>>1; 16 if(pos<=mid)update(T[x].l,T[y].l,pos,l,mid); 17 else update(T[x].r,T[y].r,pos,mid+1,r); 18 } 19 20 int ask(int x,int y,int L,int R,int l=1,int r=n) 21 { 22 if(L<=l&&r<=R)return T[y].sum-T[x].sum; 23 int mid=l+r>>1,an=0; 24 if(L<=mid)an+=ask(T[x].l,T[y].l,L,R,l,mid); 25 if(R>mid)an+=ask(T[x].r,T[y].r,L,R,mid+1,r); 26 return an; 27 } 28 29 inline int query(int x1,int x2,int y1,int y2) 30 { 31 if(x1>x2||y1>y2)return 0; 32 return ask(root[x1-1],root[x2],y1,y2); 33 } 34 35 int main(){ 36 scanf("%d%d",&n,&q); 37 F(i,1,n) 38 { 39 scanf("%d",&x); 40 update(root[i],root[i-1],x); 41 } 42 F(i,1,q) 43 { 44 int a,b,c,d; 45 scanf("%d%d%d%d",&a,&b,&c,&d); 46 ll sum=0,tmp=query(a,c,b,d); 47 sum+=1ll*query(1,a-1,1,b-1)*(query(a,n,b,n)+tmp); 48 sum+=1ll*query(a,c,1,b-1)*(query(1,n,b,n)+tmp); 49 sum+=1ll*query(c+1,n,1,b-1)*(query(1,c,b,n)+tmp); 50 sum+=1ll*query(c+1,n,b,d)*(query(1,c,1,n)+tmp); 51 sum+=1ll*query(1,a-1,b,d)*(query(a,n,1,n)+tmp); 52 sum+=1ll*query(1,a-1,d+1,n)*(query(a,n,1,d)+tmp); 53 sum+=1ll*query(a,c,d+1,n)*(query(1,n,1,d)+tmp); 54 sum+=1ll*query(c+1,n,d+1,n)*(query(1,c,1,d)+tmp); 55 sum+=tmp*(tmp-1); 56 sum/=2; 57 printf("%lld ",sum); 58 } 59 return 0; 60 }