論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即是開頭又是結尾,所以多算了一次將其減去即可):
maxi=
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
∑ng
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...