第一行有一個整數$id$,表示測試點編號。第二行有四個整數$n,m,k,q$。
而後有$k$行,每一行有四個整數$x_{i_1},y_{i_1},x_{i_2},y_{i_2}$。而後有$q$行,每一行有兩個整數$u_i,v_i$。html
有$q$行,每一行一個整數表示答案。c++
樣例輸入:算法
1
5 5 6 10
1 1 1 2
3 2 3 4
5 2 5 5
2 1 3 1
1 4 2 4
4 5 4 5
0 1
0 2
0 3
0 4
0 5
1 1
1 2
1 3
1 4
1 5測試
樣例輸出:spa
3
5
9
11
16
2
2
1
2
13d
對於全部數據,$1\leqslant id\leqslant 20$,$n,m,k\leqslant 10^5$,$q\leqslant 2n$,$1\leqslant x_{i_1}\leqslant x_{i_2}\leqslant n$,$1\leqslant y_{i_1}\leqslant y_{i_2}\leqslant m$,$u_i\in\{0,1\}$,$v_i\leqslant n$。htm
又沒有打正解,是由於沒看懂題解(我太菜辣)。blog
咱們先來考慮$u=0$的狀況,也就是咱們只須要求出樓盤總數。排序
能夠用前綴和輕鬆解決。get
那麼再來考慮$u=1$的狀況,不重疊這個性質超級棒!
先只考慮$x_{i_1}=x_{i_2}$的狀況,咱們將其按$x$爲第一維排序,$y$爲第二維排序,而後首先判斷其與前面一個有沒有聯通,在判斷其與上一行有沒有聯通,大體能夠分爲如下四種狀況$\downarrow$
你可能以爲,若是有兩個相鄰,我就將塊數$--$,可是這樣是錯的,好比下圖中的狀況$\downarrow$
而後你就去世了……
由於咱們在考慮最下面的$4$的時候發現它與$2$和$3$都相鄰,可是$2$與$3$都與$1$聯通,考慮的時候就已經在一個聯通塊裏了。
不用擔憂,並查集維護一下就好啦~
下面在來考慮通常狀況,爲方便,忽略一些能夠能夠歸爲一類的狀況,將其大體分爲一下四種狀況$\downarrow$
第一種狀況上面已經討論了,下面來看其它狀況。
咱們能夠開兩個$vector$,分別記錄每一行和每一列有哪一個矩形的$(x_{i_2},y_{i_2})$,由於本題保證了沒有重疊,因此只用記錄$(x_{i_2},y_{i_2})$,處理每個矩行的時候暴力掃一遍上一行的$vector$和相鄰列的$vector$,爲何須要掃相鄰兩列的$vector$而不是隻掃左邊這一列的,由於會出現下面這種狀況$\downarrow$
咱們在掃到紅線這一行的時候尚未掃到最下面的矩形,因此兩側的矩形還不能合併到一塊兒,而咱們在掃到最下面一行的矩形的時候才須要合併兩側的矩形。
而對於行,咱們則不用考慮這個問題,這就是上面行只用掃上面一行,而列則要掃相鄰兩列的緣由。
有了這些,就是瘋狂的調代碼了,建議現將$\forall1\leqslant i\leqslant k,x_{i_1}=x_{i_2}$的部分分拿到再衝擊正解,由於這個部分分的思想很重要。
雖然說個人算法會被極限數據卡成$\Theta(n^2)$,可是隨機數據基本上是線性的。
時間複雜度:$\Theta($玄學$)$。
指望得分:$100$分。
實際得分:$100$分。
#include<bits/stdc++.h>
using namespace std;
struct rec{int x0,x2,y0,y2;}e[100001];
int id,n,m,k,q,u,v;
int fa[100001];
long long s1[100001],s2[100001];
vector<int> vec[100002],vet[100002];
bool cmp(rec a,rec b){return a.x0==b.x0?a.y0<b.y0:a.x0<b.x0;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main()
{
scanf("%d%d%d%d%d",&id,&n,&m,&k,&q);
for(int i=1;i<=k;i++)
scanf("%d%d%d%d",&e[i].x0,&e[i].y0,&e[i].x2,&e[i].y2);
sort(e+1,e+k+1,cmp);
for(int i=1;i<=k;i++)
{
vec[e[i].y2].push_back(i);
vet[e[i].x2].push_back(i);
fa[i]=i;
}
long long sum=0;
for(int i=1;i<=k;i++)
{
if(e[i].x0==e[i].x2){s1[e[i].x0]+=e[i].y2-e[i].y0+1;s1[e[i].x0+1]-=e[i].y2-e[i].y0+1;}
else{s1[e[i].x0]++;s1[e[i].x2+1]--;}
if(e[i].x0!=e[i-1].x0)for(int j=e[i-1].x0;j<e[i].x0;j++)s2[j]=sum;
sum++;
for(int j=0;j<vet[e[i].x0-1].size();j++)
{
int x=find(i);
int y=find(vet[e[i].x0-1][j]);
if(x==y)continue;
if((e[vet[e[i].x0-1][j]].y0<=e[i].y0&&e[i].y0<=e[vet[e[i].x0-1][j]].y2)||(e[i].y0<=e[vet[e[i].x0-1][j]].y0&&e[vet[e[i].x0-1][j]].y0<=e[i].y2))
{
sum--;
fa[x]=y;
}
}
for(int j=0;j<vec[e[i].y0-1].size();j++)
{
if(e[vec[e[i].y0-1][j]].x0>e[i].x0)continue;
int x=find(i);
int y=find(vec[e[i].y0-1][j]);
if(x==y)continue;
if((e[vec[e[i].y0-1][j]].x0<=e[i].x0&&e[i].x0<=e[vec[e[i].y0-1][j]].x2)||(e[i].x0<=e[vec[e[i].y0-1][j]].x0&&e[vec[e[i].y0-1][j]].x0<=e[i].x2))
{
sum--;
fa[x]=y;
}
}
for(int j=0;j<vec[e[i].y2+1].size();j++)
{
if(e[vec[e[i].y2+1][j]].x0>e[i].x0)continue;
int x=find(i);
int y=find(vec[e[i].y2+1][j]);
if(x==y)continue;
if((e[vec[e[i].y2+1][j]].x0<=e[i].x0&&e[i].x0<=e[vec[e[i].y2+1][j]].x2)||(e[i].x0<=e[vec[e[i].y2+1][j]].x0&&e[vec[e[i].y2+1][j]].x0<=e[i].x2))
{
sum--;
fa[x]=y;
}
}
}
for(int i=e[k].x0;i<=n;i++)s2[i]=sum;
for(int i=1;i<=n;i++)s1[i]+=s1[i-1];
for(int i=1;i<=n;i++)s1[i]+=s1[i-1];
while(q--)
{
scanf("%d%d",&u,&v);
if(u)printf("%lld\n",s2[v]);
else printf("%lld\n",s1[v]);
}
return 0;
}
rp++