【bzoj2244】[SDOI2011]拦截导弹

来源:互联网 发布:江西理工大学软件学院 编辑:程序博客网 时间:2024/06/06 04:06

这题就是个三维偏序。

三维偏序就是排序一维,cdq一维,数据结构一维。

然后尴尬的是还要求概率。

也就是方案数。

cdq正反各一遍,求三维偏序时,顺便dp记录方案数就好。

#include <bits/stdc++.h>#define gc getchar()#define N 50009#define mid (l+r>>1)#define ll long longusing namespace std;int n,dp[N],ans,bit[N],len,DP[N];double sum=0.0,g[N],G[N],bit_g[N];vector<int> q;struct node{int x,y,pd,pos;bool operator <(const node &rhs) const{return x<rhs.x||(x==rhs.x&&y<rhs.y)||(x==rhs.x&&y==rhs.y&&pd);}}p[N],now[N],P[N];int read(){int x=1;char ch;while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;int s=ch-'0';while (ch=gc,ch<='9'&&ch>='0') s=s*10+ch-'0';return s*x;}int lowbit(int x){return x&(-x);}void ins(int x,int y,double z){for (;x<=n;x+=lowbit(x))if (bit[x]==y) bit_g[x]+=z;else if (bit[x]<y) bit[x]=y,bit_g[x]=z;}void back(int x){for (;x<=n;x+=lowbit(x)) bit[x]=bit_g[x]=0;}int qry(int x,double &sum,int ret=0){for (;x;x-=lowbit(x))if (ret==bit[x]) sum+=bit_g[x];else if (ret<bit[x]) ret=bit[x],sum=bit_g[x];return ret;}void solve(int l,int r){if (l==r){if (!dp[l]) dp[l]=g[l]=1;return;}solve(l,mid);int m=0;for (int i=l;i<=r;i++) now[++m]=p[i],now[m].pd=(i<=mid),now[m].pos=i;sort(now+1,now+m+1);for (int i=1;i<=m;i++)if (now[i].pd) ins(now[i].y,dp[now[i].pos],g[now[i].pos]);else{double now_sum=0;int now_ans=qry(now[i].y,now_sum)+1;if (now_ans==1) continue;if (now_ans>dp[now[i].pos])dp[now[i].pos]=now_ans,g[now[i].pos]=now_sum;elseif (now_ans==dp[now[i].pos])g[now[i].pos]+=now_sum;}for (int i=1;i<=m;i++)if (now[i].pd) back(now[i].y);solve(mid+1,r);}void SOLVE(int l,int r){if (l==r){if (!DP[l]) DP[l]=G[l]=1;return;}SOLVE(l,mid);int m=0;for (int i=l;i<=r;i++) now[++m]=P[i],now[m].pd=(i<=mid),now[m].pos=i;sort(now+1,now+m+1);for (int i=1;i<=m;i++)if (now[i].pd) ins(now[i].y,DP[now[i].pos],G[now[i].pos]);else{double now_sum=0;int now_ans=qry(now[i].y,now_sum)+1;if (now_ans==1) continue;if (now_ans>DP[now[i].pos])DP[now[i].pos]=now_ans,G[now[i].pos]=now_sum;elseif (now_ans==DP[now[i].pos])G[now[i].pos]+=now_sum;}for (int i=1;i<=m;i++)if (now[i].pd) back(now[i].y);SOLVE(mid+1,r);}int main(){n=read();for (int i=n;i>=1;i--) p[i].x=read(),p[i].y=read(),q.push_back(p[i].y);sort(q.begin(),q.end());len=unique(q.begin(),q.end())-q.begin();for (int i=1;i<=n;i++)p[i].y=lower_bound(q.begin(),q.end(),p[i].y)-q.begin()+1;solve(1,n);for (int i=1;i<=n;i++) ans=max(ans,dp[i]);for (int i=1;i<=n;i++)if (ans==dp[i]) sum+=g[i]*G[n-i+1];for (int i=1;i<=n;i++) P[i]=p[n-i+1],P[i].x=-P[i].x,P[i].y=n-P[i].y+1;//for (int i=1;i<=n;i++) cout<<P[i].x<<" "<<P[i].y<<endl;SOLVE(1,n);//for (int i=1;i<=n;i++) cout<<G[i]<<endl;printf("%d\n",ans);for (int i=1;i<=n;i++)if (dp[n-i+1]+DP[i]==ans+1)printf("%.5lf%s",g[n-i+1]*G[i]/sum,i==n?"\n":" ");elseprintf("%.5lf%s",0.0,i==n?"\n":" ");return 0;}


原创粉丝点击