首页 > 代码库 > BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治
BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治
2244: [SDOI2011]拦截导弹
Description
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
Input
第一行包含一个正整数n,表示敌军导弹数量;
下面 行按顺序给出了敌军所有导弹信息:
第i+1行包含2个正整数hi和vi,分别表示第 枚导弹的高度和速度。
Output
输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含n个0到1之间的实数,第i个数字表示第i枚导弹被拦截掉的概率(你可以保留任意多位有效数字)。
Sample Input
4
3 30
4 40
6 60
3 30
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。
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_pairtypedef 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;}
#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;}
BZOJ 2244: [SDOI2011]拦截导弹 DP+CDQ分治
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。