SDOI2011 攔截飛彈

2021-10-05 16:05:05 字數 3949 閱讀 5849

點此看題

設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 某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度 並且能夠攔截任意速度的飛彈,但是以後每一發炮彈都不能高於前一發的高度,其攔截的飛彈的飛行速度也不能大於前一發。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還...