Codeforces Round #433 (Div. 2) E. Boredom(主席树)

题目链接: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 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7489867.html