SDOI2011 飛彈攔截 題解

2022-05-16 10:30:57 字數 3882 閱讀 7762

論printf("%lf",0.0)的重要性

給你nn

個三維的點(x,

y,z)

(x,y

,z),求出最長的三維不下降序列,並輸出每乙個點在最長的序列上的概率。

這個肯定和普通的飛彈攔截不同了,普通的是沒有速度的,也就是二維的,且時間一維已經有序,那麼對高度求乙個lis

lis(最長不下降序列)就好了。

但是現在還有速度一維,所以不能簡單的做了。

那麼有三個限制條件的lis

lis,顯然就是乙個三維偏序的問題,所以根據套路,我們對一維排序,一維cdq

cdq,一維資料結構就行了。

對於要求取概率,我們不能直接求出(因為不清楚是否在最優方案上),所以我們對其進行兩次的求取lis

lis,從前往後求一遍最長不下降序列,再從後往前求一遍最長不上公升序列,分別記為f1[

i],f

2[i]

f1​[

i],f

2​[i

],表示以第i

i個點為結尾或者開頭的最長長度,那麼答案就是(減一是因為這個點i

i即是開頭又是結尾,所以多算了一次將其減去即可):

max⁡i=

1ni=

1maxn​

所以判斷乙個點是否在最長的上面只需要判斷f1[

i]+f

2[i]

−1f1

​[i]

+f2​

[i]−

1是否等於ans

ans即可。

那麼對於方案數,我們同樣在兩次求取中統計一下,分別記為g1[

i],g

2[i]

g1​[

i],g

2​[i

],那麼乙個點在它最長的情況下的方案數就等於g1[

i]×g

2[i]

g1​[

i]×g

2​[i

]所以我們先統計最長情況下的總方案數:su

m=∑i

=1ng

1[i]

×g2[

i](要滿足f1

[i]+

f2[i

]−1=

=ans

)sum

=i=1

∑n​g

1​[i

]×g2

​[i]

(要滿足f1

​[i]

+f2​

[i]−

1==a

ns)那麼對於在最長的上面的飛彈被攔截的概率為g1[

i]×g

2[i]

sums

umg1

​[i]

×g2​

[i]​

,不在的話就直接為00了。

這裡我使用的樹狀陣列下標為速度維護dpd

p陣列,所以還需要離散化一下。

下面上**常數略大長度略長

#include

#include

#include

#define db double

#define lowbit(a) ((a)&(-(a)))

using

namespace std;

const

int m=

1e5+10;

int n,ans;

int id[m]

;int ls[m]

,tot;

int vs[m]

,tst;

db sum;

struct node

}a[m]

,q[m]

;bool

cmp(

int a,

int b)

struct bit_tree

else

if(f[a]

==ff)}}

void

query

(int a,

int&ff,db &gg)

else

if(ff==f[a])}

}void

clear()

}b;void

solve

(int l,

int r,

bool type)

return;}

int mid=

(l+r)

>>1;

int t1=l,t2=mid+1;

for(

int i=l;i<=r;i++

)for

(int i=l;i<=r;i++

)a[i]

=q[i]

;solve

(l,mid,type)

;//遞迴處理

t1=l;

int ff=

0;db gg=0;

for(

int i=mid+

1;i<=r;i++

)else

if(ff+

1==a[i]

.f[type]

)//更新方案和長度

}while

(b.top>

0)b.

clear()

;//優化清除空間

solve

(mid+

1,r,type)

;sort

(a+l,a+r+1)

;//最後按照時間排序!!!

}int a,b;

intmain()

sort

(ls+

1,ls+tot+1)

; tot=

unique

(ls+

1,ls+tot+1)

-ls-1;

sort

(vs+

1,vs+tst+1)

; tst=

unique

(vs+

1,vs+tst+1)

-vs-1;

//離散化

for(

int i=

1;i<=n;i++

) a[i]

.h=lower_bound

(ls+

1,ls+tot+

1,a[i]

.h)-ls,

a[i]

.v=lower_bound

(vs+

1,vs+tst+

1,a[i]

.v)-vs;

for(

int i=

1;i<=n;i++

)sort

(id+

1,id+n+

1,cmp)

;//按照高度排序

for(

int i=

1;i<=n;i++

)a[id[i]

].sid=i;

solve(1

,n,0);

//處理順

for(

int i=

1;i<=n;i++

)//翻轉處理倒起

reverse

(a+1

,a+n+1)

;solve(1

,n,1);

reverse

(a+1

,a+n+1)

;int vv=0;

for(

int i=

1;i<=n;i++

)//找最大長度,減1是因為當前這個點被算了兩次

printf

("%d\n"

,ans)

;for

(int i=

1;i<=n;i++

)//求取總方案數

for(

int i=

1;i<=n;i++

)return0;

}

SDOI2011 攔截飛彈

點此看題 設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...

SDOI2011 攔截飛彈

這道題是真的蛇皮 方案數要開 double 真的蛇皮 首先 dp 是非常容易看出來的 設 dp i 表示以 i 結尾的最長子序列 顯然轉移方程為 dp i max dp j 1 j h i v j v i 暴力轉移是 o n 2 的 同時第二問我們還需要求乙個概率 非常簡單,我們反正做一遍 dp 看...

SDOI2011 染色 題解

題目大意 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色被認為是同一段 思路 樹剖之後,維護其兩端的顏色 答案和標記即可。include include define n 100001 using...