日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治

發布時間:2025/4/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2244: [SDOI2011]攔截導彈


Description

某國為了防御敵國的導彈襲擊,發展出一種導彈攔截系統。但是這種導彈攔截系統有一個缺陷:雖然它的第一發炮彈能夠到達任意的高度、并且能夠攔截任意速度的導彈,但是以后每一發炮彈都不能高于前一發的高度,其攔截的導彈的飛行速度也不能大于前一發。某天,雷達捕捉到敵國的導彈來襲。由于該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的導彈。

在不能攔截所有的導彈的情況下,我們當然要選擇使國家損失最小、也就是攔截導彈的數量最多的方案。但是攔截導彈數量的最多的方案有可能有多個,如果有多個最優方案,那么我們會隨機選取一個作為最終的攔截導彈行動藍圖。

我方間諜已經獲取了所有敵軍導彈的高度和速度,你的任務是計算出在執行上述決策時,每枚導彈被攔截掉的概率。

?

Input

第一行包含一個正整數n,表示敵軍導彈數量;

下面?行按順序給出了敵軍所有導彈信息:

i+1行包含2個正整數hivi,分別表示第?枚導彈的高度和速度。

?

Output

輸出包含兩行。

第一行為一個正整數,表示最多能攔截掉的導彈數量;

第二行包含n個0到1之間的實數,第i個數字表示第i枚導彈被攔截掉的概率(你可以保留任意多位有效數字)。

?

Sample Input

4

3 30

4 40

6 60

3 30

Sample Output

2

0.33333 0.33333 0.33333 1.00000

【數據規模和約定】


對于100%的數據,1≤n≤5*104, 1≤hi ,vi≤109;

均勻分布著約30%的數據,所有vi均相等。

均勻分布著約50%的數據,滿足1≤hi ,vi≤1000。

HINT

?

題解:

  因為精度的問題wa了一天

  設定dp[i][0/1] 表示正向和反向的LIS,f[i][0/1] 為其方案數

  繼承是一個三維偏序,一維排序,二維CDQ,三維樹狀數組,一次解決

  下面是兩份不同的代碼

#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,double> #define MP make_pair typedef long long LL; typedef unsigned long long ULL; const long long INF = 1e18+1LL; const double pi = acos(-1.0); const int N = 2e5+10, M = 1e3+20,inf = 2e9; struct ss{int t,x,y;/*bool operator < (const ss &r) const {return x == r.x ? y<r.y : x < r.x;}*/ }a[N],t[N];bool cmp1(ss s1,ss s2) {return s1.t < s2.t; }bool cmp2(ss s1,ss s2) {if(s1.x == s2.x) {if(s1.y == s2.y) return s1.t < s2.t;else return s1.y > s2.y;}return s1.x > s2.x; }vector<double > ans; int dp[N][2],scc = 0,tag[N]; double f[N][2]; int n; pair<int,double > C[N],C1[N]; void update(int x,pii now) {for(int i = x; i ; i -= i&-i) {if(now.first == 0)C[i] = MP(0,0);else {if(C[i].first < now.first) {C[i] = now;}else if(C[i].first == now.first) {C[i].second += now.second;}}} } pii ask(int x) {pii ret = MP(0,0);for(int i = x; i <= n; i += i&-i) {if(ret.first < C[i].first) {ret = C[i];}else if(ret.first == C[i].first){ret.second += C[i].second;}}return ret;} void cdq(int ll,int rr,int p) {if(ll == rr) {if( f[ll][p] == 0) {dp[ll][p] = 1;f[ll][p] = 1;}return ;}sort(a+ll,a+rr+1,cmp1);cdq(ll,mid,p);scc++;sort(a+ll,a+rr+1,cmp2);for(int i = ll; i <= rr; ++i) {if(a[i].t <= mid) {update(a[i].y,MP(dp[a[i].t][p],f[a[i].t][p]));}else {pii now = ask(a[i].y);now.first += 1;if(now.second == 0) continue;if(now.first > dp[a[i].t][p]) {dp[a[i].t][p] = now.first;f[a[i].t][p] = now.second;}else if(now.first == dp[a[i].t][p]){f[a[i].t][p] += now.second;}}}for(int i = ll; i <= rr; ++i) {if(a[i].t <= mid) update(a[i].y,MP(0,0));}sort(a+ll,a+rr+1,cmp1);cdq(mid+1,rr,p); } int cnt[N],san[N],cnts; int main() {scanf("%d",&n);int mxxx = 0;for(int i = 1; i <= n; ++i) {scanf("%d%d",&a[i].x,&a[i].y);san[i] = a[i].y;mxxx = max(mxxx,a[i].x);a[i].t = i;}sort(san+1,san+n+1);int SA = unique(san+1,san+n+1) - san - 1;for(int i = 1; i <= n; ++i)a[i].y = lower_bound(san+1,san+SA+1, a[i].y) - san;cdq(1,n,0);sort(a+1,a+n+1,cmp1);for(int i =1; i <= n; ++i) {a[i].y = SA - a[i].y + 1;a[i].x = mxxx - a[i].x + 1;}for(int i = 1; i <= n/2; ++i) {swap(a[i].x,a[n - i + 1].x);swap(a[i].y,a[n - i + 1].y);}cdq(1,n,1);int ans = 0;for(int i = 1; i <= n; ++i) {ans = max(ans,(int)dp[i][0]);}printf("%d\n",ans);double sum = 0.0;for(int i = 1; i <= n; ++i) {if(dp[i][0] == ans) sum += (double)f[i][0] * f[n-i+1][1];}for(int i = 1; i <= n; ++i) {if(dp[i][0] + dp[n-i+1][1] - 1 == ans) {printf("%.5lf",(double)f[i][0] * f[n-i+1][1] / sum);}else printf("%.5lf",0.0);if(i == n) printf("\n");else printf(" ");}return 0; } View Code #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; typedef unsigned long long ULL; const int N = 1e5+10, M = 1e3+20,inf = 2e9;double f[N][2]; double dp[N][2]; int ch[N]; struct ss {int t,x,y; }a[N],t1[N],t2[N]; int cmp(ss s1,ss s2) {return s1.x > s2.x; } double C[N]; double D[N]; double first; double second; void update(int x,double firs,double secon) {for(int i = x; i < N; i += i&(-i)) {if(C[i] < firs) {C[i] = firs;D[i] = secon;}else if(C[i] == firs) {D[i] += secon;}} }void ask(int x) {first = 0.0,second = 0.0;for(int i = x; i >= 1; i -= i&(-i)) {if(C[i] > first) {first = C[i];second = D[i];}else if(C[i] == first) {second += D[i];}} } void go(int x) {for(int i = x; i < N; i += i & (-i)) {C[i] = 0,D[i] = 0;} } void CDQ(int ll,int rr,int p) {if(ll == rr) {f[ll][p] = max(f[ll][p],1.0);dp[ll][p] = max(dp[ll][p],1.0);return ;}int mid = (ll+rr)>>1;CDQ(ll,mid,p);int acnt = 0, bcnt = 0, tot = 0;for(int i = ll; i <= mid; ++i) t1[++acnt] = a[i];for(int i = mid+1; i <= rr; ++i) t2[++bcnt] = a[i];sort(t1+1,t1+acnt+1,cmp);sort(t2+1,t2+bcnt+1,cmp);int pa = 1,pb = 1;while(pb <= bcnt) {while(pa <= acnt && t1[pa].x >= t2[pb].x) {update(t1[pa].y,dp[t1[pa].t][p],f[t1[pa].t][p]);ch[++tot] = t1[pa].y;pa++;}ask(t2[pb].y);//cout<<first<<" "<<second<<endl;int id = t2[pb].t;if(first + 1 > dp[id][p]) {dp[id][p] = first+1;f[id][p] = second;}else if(first + 1 == dp[id][p])f[id][p] += second;pb++;}for(int i = 1; i <= tot; ++i) go(ch[i]);CDQ(mid+1,rr,p); } int n,san[N],SA; int main() {int mx = -1;scanf("%d",&n);for(int i = 1; i <= n; ++i) {scanf("%d%d",&a[i].x,&a[i].y);san[i] = a[i].y;a[i].t = i;mx = max(a[i].x,mx);}sort(san+1,san+n+1);SA = unique(san+1,san+n+1) - san - 1;for(int i = 1; i <= n; ++i)a[i].y = lower_bound(san+1,san+SA+1,a[i].y) - san;for(int i = 1; i <= n; ++i) {a[i].y = SA - a[i].y + 1;}CDQ(1,n,0);for(int i = 1; i <= n; ++i) {a[i].y = SA - a[i].y + 1;a[i].x = mx - a[i].x + 1;}reverse(a+1,a+n+1);for(int i = 1; i <= n; ++i) {a[i].t = i;}CDQ(1,n,1);int ans = 0;for(int i = 1; i <= n; ++i) {ans = max(ans,(int)dp[i][0]);}printf("%d\n",ans);double sum = 0.0;for(int i = 1; i <= n; ++i) {if(dp[i][0] == ans) sum += (double)f[i][0] * f[n-i+1][1];}for(int i = 1; i <= n; ++i) {if(dp[i][0] + dp[n-i+1][1] - 1 == ans) {printf("%.5lf",(double)f[i][0] * f[n-i+1][1] / sum);}else printf("%.5lf",0.0);if(i == n) printf("\n");else printf(" ");}return 0; }

?

轉載于:https://www.cnblogs.com/zxhl/p/7243204.html

總結

以上是生活随笔為你收集整理的BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。