點此看題
設f [i
]f[i]
f[i]
為以i
ii點結束的最長不降子串行個數,可以cdq
cdqcd
q分治,遞迴的時候我們已經處理出了[l,
mid]
[l,mid]
[l,mid
]的ff
f值,我們要拿他去更新[mi
d+1,
r]
[mid+1,r]
[mid+1
,r]的f
ff值,需要滿足hi≥
hj,v
i≥vj
h_i\geq h_j,v_i\geq v_j
hi≥hj
,vi
≥vj
才能更新,所以我們先按h
hh從大到小排序,然後維護出乙個最大值的線段樹(跟經典的三維偏序十分類似),然後我們遞迴[mi
d+1,
r]
[mid+1,r]
[mid+1
,r],實現中有乙個細節,就是最開始要按t
tt(給出時間)排序,因為順序可能被打亂了。
第一問就解決了,第二問的話就在dpdp
dp過程中維護乙個方案數(線段樹里同時也需要),我們處理出以i
ii結尾的最長不降子串行,以i
ii開始的最長不降子串行,處理方法就是反向跑兩遍,就能判斷乙個點是否在最優解中,然後用乘法原理把兩者的方案數乘起來,除以總最優解個數就是概率。
#include
#include
#include
using
namespace std;
#define db double
#define int long long
const
int m =
50005
;int
read()
int n,m,mh,ans,a[m]
,f1[m]
,f2[m]
,mx[
4*m]
;db sum,g1[m]
,g2[m]
,cnt[
4*m]
;struct node
p[m]
;bool
cmp1
(node a,node b)
bool
cmp2
(node a,node b)
void
upd(
int i,
int l,
int r,
int id,
int v,db t)
int mid=
(l+r)
>>1;
if(mid>=id)
upd(i<<
1,l,mid,id,v,t)
;else
upd(i<<1|
1,mid+
1,r,id,v,t)
; mx[i]
=max
(mx[i<<1]
,mx[i<<1|
1]);
cnt[i]=0
;if(mx[i]
==mx[i<<1]
) cnt[i]
+=cnt[i<<1]
;if(mx[i]
==mx[i<<1|
1]) cnt[i]
+=cnt[i<<1|
1];}
intask
(int i,
int l,
int r,
int l,
int r,db &t)
if(l<=l && r<=r)
int mid=
(l+r)
>>
1;db tl=
0,tr=0;
int a1=
ask(i<<
1,l,mid,l,r,tl)
,a2=
ask(i<<1|
1,mid+
1,r,l,r,tr);if
(max
(a1,a2)
==a1) t+
=tl;if(
max(a1,a2)
==a2) t+
=tr;
return
max(a1,a2);}
void
clear
(int i,
int l,
int r)
void
cdq1
(int l,
int r)
db cnt=0;
int t=
ask(1,
1,n,p[j]
.v,n,cnt);if
(!t)
continue;if
(f1[p[j]
.t]1) f1[p[j]
.t]=t+
1,g1[p[j]
.t]=0;
if(f1[p[j]
.t]==t+
1) g1[p[j]
.t]+
=cnt;
}cdq1
(mid+
1,r);}
void
cdq2
(int l,
int r)
db cnt=0;
int t=
ask(1,
1,n,p[j]
.v,n,cnt);if
(!t)
continue;if
(f2[p[j]
.t]1) f2[p[j]
.t]=t+
1,g2[p[j]
.t]=0;
if(f2[p[j]
.t]==t+
1) g2[p[j]
.t]+
=cnt;
}cdq2
(mid+
1,r);}
signed
main()
sort
(a+1
,a+1
+n);
m=unique
(a+1
,a+1
+n)-a-1;
for(
int i=
1;i<=n;i++
) p[i]
.v=lower_bound
(a+1
,a+1
+m,p[i]
.v)-a;
for(
int i=
1;i<=n;i++
) f1[i]
=g1[i]
=f2[i]
=g2[i]=1
;cdq1(1
,n);
for(
int i=
1;i<=n;i++
) ans=
max(ans,f1[i]);
for(
int i=
1;i<=n;i++)if
(ans==f1[i]
) sum+
=g1[i]
;sort
(p+1
,p+1
+n,cmp1)
;for
(int i=
1;i<=n;i++
) p[i]
.t=n-p[i]
.t+1
,p[i]
.h=mh-p[i]
.h+1
,p[i]
.v=n-p[i]
.v+1
;cdq2(1
,n);
printf
("%lld\n"
,ans)
;for
(int i=
1;i<=n;i++
)}
SDOI2011 攔截飛彈
這道題是真的蛇皮 方案數要開 double 真的蛇皮 首先 dp 是非常容易看出來的 設 dp i 表示以 i 結尾的最長子序列 顯然轉移方程為 dp i max dp j 1 j h i v j v i 暴力轉移是 o n 2 的 同時第二問我們還需要求乙個概率 非常簡單,我們反正做一遍 dp 看...
SDOI2011 飛彈攔截 題解
論printf lf 0.0 的重要性 給你nn 個三維的點 x,y,z x,y z 求出最長的三維不下降序列,並輸出每乙個點在最長的序列上的概率。這個肯定和普通的飛彈攔截不同了,普通的是沒有速度的,也就是二維的,且時間一維已經有序,那麼對高度求乙個lis lis 最長不下降序列 就好了。但是現在還...
SDOI2011 BZOJ2244 攔截飛彈
description 某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度 並且能夠攔截任意速度的飛彈,但是以後每一發炮彈都不能高於前一發的高度,其攔截的飛彈的飛行速度也不能大於前一發。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還...