生活随笔
收集整理的這篇文章主要介紹了
HDU - 6992 Lawn of the Dead 线段树 + 思维
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
給你一張n?mn*mn?m的圖,其中有kkk個點不能走,你只能向下和向右走,問你能到達多少點。
n,m,k≤1e5n,m,k\le1e5n,m,k≤1e5
思路:
可以發現每個點如果其左邊和上面都有障礙,那么這個點不可達。考慮到障礙數量比較少,所以肯定是枚舉障礙的數量,現在就變成怎么快速統計答案了。
我們按照每一列來考慮,下面是樣例的圖,其中三角形代表障礙。
對于每個位置(x,y)(x,y)(x,y),我們查詢其它上面障礙出現的位置(如果之前沒有障礙我們定義為000)之后到(x?1,y?1)(x-1,y-1)(x?1,y?1)的位置中第一次空位置,即能走的位置,將這個位置到當前位置之前都賦值為111,代表這些點可達。
下圖中問號即為詢問的區間,箭頭指向(x?1,y?1)(x-1,y-1)(x?1,y?1)。
區間查詢以及區間覆蓋的操作顯然可以用線段樹來實現,再加點邊界限制即可。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
,m
,k
;
vector
<int>v
[N
];
struct Seg {struct Node{int l
,r
;int sum
;int lazy
;}tr
[N
<<2];void pushup(int u
) {tr
[u
].sum
=tr
[L
].sum
+tr
[R
].sum
;}void pushdown(int u
) {if(tr
[u
].lazy
!=-1) {int lazy
=tr
[u
].lazy
; tr
[u
].lazy
=-1; tr
[L
].sum
=Len(L
)*lazy
; tr
[L
].lazy
=lazy
;tr
[R
].sum
=Len(R
)*lazy
; tr
[R
].lazy
=lazy
;} }void build(int u
,int l
,int r
) {tr
[u
]={l
,r
,0,-1};if(l
==r
) return;build(L
,l
,Mid
); build(R
,Mid
+1,r
);}void modify(int u
,int l
,int r
,int x
) {if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) {tr
[u
].sum
=Len(u
)*x
;tr
[u
].lazy
=x
;return;}pushdown(u
);if(l
<=Mid
) modify(L
,l
,r
,x
);if(r
>Mid
) modify(R
,l
,r
,x
);pushup(u
); }int query(int u
,int l
,int r
) {if(tr
[u
].sum
==0) return INF
;if(tr
[u
].l
==tr
[u
].r
) return tr
[u
].l
;pushdown(u
);if(tr
[u
].l
>=l
&&tr
[u
].r
<=r
) {if(tr
[L
].sum
>0) return query(L
,l
,r
);else return query(R
,l
,r
);}int ans
=INF
;if(l
<=Mid
) ans
=min(ans
,query(L
,l
,r
));if(r
>Mid
) ans
=min(ans
,query(R
,l
,r
));return ans
;}}t
[2];int main()
{
int _
; scanf("%d",&_
);for(int __
=1;__
<=_
;__
++) {scanf("%d%d%d",&n
,&m
,&k
);for(int i
=1;i
<=m
;i
++) v
[i
].clear();for(int i
=1;i
<=k
;i
++) {int x
,y
; scanf("%d%d",&x
,&y
);v
[y
].pb(x
);} t
[0].build(1,1,n
); t
[1].build(1,1,n
);int now
=0; t
[now
].modify(1,1,1,1); now
^=1;LL ans
=0;for(int i
=1;i
<=m
;i
++) {sort(v
[i
].begin(),v
[i
].end());int l
=0;for(auto x
:v
[i
]) {if(l
+1<=x
-1) {int pos
=t
[now
^1].query(1,l
+1,x
-1);if(pos
!=INF
) t
[now
].modify(1,pos
,x
-1,1);}l
=x
;}if(l
+1<=n
) {int pos
=t
[now
^1].query(1,l
+1,n
);if(pos
!=INF
) t
[now
].modify(1,pos
,n
,1);}ans
+=t
[now
].tr
[1].sum
;t
[now
^1].modify(1,1,n
,0);now
^=1;}printf("%lld\n",ans
);}return 0;
}
總結
以上是生活随笔為你收集整理的HDU - 6992 Lawn of the Dead 线段树 + 思维的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。