**
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
**
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
**
鸣谢kac提供sj程序!
**
Source
**
第一轮day2
**
Sotution
**
三维偏序——一维排序 二维cdq分治 三维树状数组 然后再做两遍LIS 通过正反和-1==ans 来判断某个数是不是在最后的答案里
代码能力太弱QAQ
**
Code
**
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e4+10;
struct data{
int x,y,z,f[2];double g[2];
data(){x=y=z=f[1]=f[0]=0;g[0]=g[1]=0;}
}d[maxn],t[maxn];
bool operator <(data a,data b){return a.y<b.y||(a.y==b.y&&a.x<b.x);}
inline bool cmp(data x,data y){return x.x<y.x;}
struct Bit{
int w;double sum;
Bit(){w=0;sum=0;}
inline void clear(){w=0;sum=0;}
}qu[maxn];
int sta[maxn],tot,n,haz[maxn],hay[maxn],tpz,tpy;
inline Bit ask(int x)
{
Bit res;
while(x)
{
if(qu[x].w>res.w)res=qu[x];
else if(qu[x].w==res.w)res.sum+=qu[x].sum;
x-=x&-x;
}
return res;
}
void update(int x,int w,double s)
{
while(x<=tpz)
{
if(qu[x].w<w)
{
if(qu[x].w==0)sta[++tot]=x;
qu[x].w=w;qu[x].sum=s;
}
else if(qu[x].w==w)qu[x].sum+=s;
x+=x&-x;
}
}
void solve(int l,int r,int p)
{
if(l==r){if(d[l].f[p]<1)d[l].f[p]=d[l].g[p]=1;return;}
int mid=(l+r)>>1,st=l,ed=mid+1;
for(int i=l;i<=r;i++)
if(d[i].x<=mid)t[st++]=d[i];
else t[ed++]=d[i];
for(int i=l;i<=r;i++)d[i]=t[i];
solve(l,mid,p);
sort(d+l,d+mid+1);st=l;
for(int i=mid+1;i<=r;i++)
{
while(st<=mid&&d[i].y>=d[st].y)update(d[st].z,d[st].f[p],d[st].g[p]),st++;
Bit res=ask(d[i].z);
if(!res.w)continue;
if(res.w+1>d[i].f[p])d[i].f[p]=res.w+1,d[i].g[p]=res.sum;
else if(res.w+1==d[i].f[p])d[i].g[p]+=res.sum;
}
for(int i=1;i<=tot;i++)qu[sta[i]].clear();tot=0;
solve(mid+1,r,p);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&d[i].y,&d[i].z),d[i].x=i,hay[i]=d[i].y,haz[i]=d[i].z;
sort(hay+1,hay+1+n);sort(haz+1,haz+1+n);
tpy=unique(hay+1,hay+1+n)-hay-1;tpz=unique(haz+1,haz+1+n)-haz-1;
for(int i=1;i<=n;i++)
d[i].y=tpy-(lower_bound(hay+1,hay+1+tpy,d[i].y)-hay)+1,d[i].z=tpz-(lower_bound(haz+1,haz+1+tpz,d[i].z)-haz)+1;
sort(d+1,d+1+n);
solve(1,n,0);
for(int i=1;i<=n;i++)
d[i].x=n-d[i].x+1,d[i].y=tpy-d[i].y+1,d[i].z=tpz-d[i].z+1;
reverse(d+1,d+1+n);sort(d+1,d+1+n);
solve(1,n,1);
int ans=0;double Sum;
sort(d+1,d+1+n,cmp);
reverse(d+1,d+1+n);
for(int i=1;i<=n;i++)
if(ans<d[i].f[0])//寻找最长的LIS
{
ans=d[i].f[0];
Sum=d[i].g[0];
}
else if(ans==d[i].f[0])
Sum+=d[i].g[0];
printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
int len=d[i].f[0]+d[i].f[1]-1;
if(len<ans)printf("0.00000 ");
else printf("%.5lf ",d[i].g[0]*d[i].g[1]/Sum);
}
return 0;
}
——看不见光明,只能摸索