您的位置:首页 > 其它

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

2016-04-16 13:27 302 查看
%%% PoPoQQQ/article/2348576.html

“第一问CDQ分治裸上

第二问用每个元素所在的LIS个数/总LIS个数就是答案

每个元素所在的LIS自己必选,然后统计前面的方案数和后面的方案数

以前面的方案数为例,令f[x]为以x结尾的LIS长度,那么有DP方程:

g[i]=Σg[j] (f[j]+1=f[i],j<i,a[j].x<a[i].x,a[j].y<a[i].y)

将所有元素按f值排序,分层DP,每层DP是一个三维偏序,上CDQ分治再搞搞就好了”

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}

inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

int ans;
int n,h[50005],v[50005];
int f[50005];

int sx[100005],icnt;
inline int Bin(int x){
return lower_bound(sx+1,sx+icnt+1,x)-sx;
}

namespace CDQ{
namespace BIT{
#define lowbit(x) ((x)&-(x))
int maxn;
int c[100005];
inline void init(int n){
maxn=n;
}
inline void add(int x,int r){
for (int i=x;i<=maxn;i+=lowbit(i))
c[i]=max(c[i],r);
}
inline void clr(int x){
for (int i=x;i<=maxn;i+=lowbit(i))
c[i]=0;
}
inline int sum(int x){
int ret=0;
for (int i=x;i;i-=lowbit(i))
ret=max(ret,c[i]);
return ret;
}
}
struct event{
int x,y;
int idx;
bool operator < (const event &B) const{
return x==B.x?y<B.y:x<B.x;
}
}eve[50005],tmp[50005];
inline void cdq(int l,int r){
if (l==r) return;
int mid=(l+r)>>1;
cdq(l,mid);
for (int i=l;i<=r;i++) tmp[i]=eve[i];
sort(eve+l,eve+mid+1); sort(eve+mid+1,eve+r+1);
int i=l,j=mid+1;
while (j<=r) {
while (i<=mid && eve[i].x<=eve[j].x)
BIT::add(eve[i].y,f[eve[i].idx]),i++;
f[eve[j].idx]=max(f[eve[j].idx],BIT::sum(eve[j].y)+1);
j++;
}
for(int j=l;j<i;j++) BIT::clr(eve[j].y);
for (int i=l;i<=r;i++) eve[i]=tmp[i];
cdq(mid+1,r);
}
inline void Solve(){
BIT::init(icnt);
for (int i=1;i<=n;i++)
eve[i].idx=i,eve[i].x=Bin(h[i]),eve[i].y=Bin(v[i]),f[i]=1;
cdq(1,n);
ans=0;
for (int i=1;i<=n;i++)
ans=max(ans,f[i]);
printf("%d\n",ans);
}
}

namespace BIT{
#define lowbit(x) ((x)&-(x))
int maxn;
double c[100005];
inline void init(int n){
maxn=n;
}
inline void add(int x,double r){
for (int i=x;i<=maxn;i+=lowbit(i))
c[i]+=r;
}
inline void clr(int x){
for (int i=x;i<=maxn;i+=lowbit(i))
c[i]=0;
}
inline double sum(int x){
double ret=0;
for (int i=x;i;i-=lowbit(i))
ret+=c[i];
return ret;
}
inline double sum(int l,int r){
return sum(r)-sum(l-1);
}
}

struct event{
int f,x,y;
int idx;
}eve[50005],itmp[50005],tmp[50005];

double tot,pre[50005],nxt[50005],Ans[50005];
int L[50005],R[50005];

bool cmpidx(event A,event B){
return A.idx<B.idx;
}
bool cmpxy(event A,event B){
return A.x==B.x?A.y<B.y:A.x<B.x;
}
bool cmpf(event A,event B){
return A.f<B.f;
}

inline void cdq1(int l,int r,int k){
if (l==r) return;
int mid=(l+r)>>1;
cdq1(l,mid,k);
cdq1(mid+1,r,k);
sort(eve+l,eve+mid+1,cmpxy);
sort(eve+mid+1,eve+r+1,cmpxy);
int i=l,j=mid+1;
while(j<=r)
{
while(i<=mid&&eve[i].x<=eve[j].x)
{
if (eve[i].f==k-1)
BIT::add(eve[i].y,pre[eve[i].idx]);
i++;
}
if (eve[j].f==k)
pre[eve[j].idx]+=BIT::sum(eve[j].y);
j++;
}
for(int j=l;j<i;j++)
if (eve[j].f==k-1)
BIT::clr(eve[j].y);
}

inline void cdq2(int l,int r,int k){
if (l==r) return;
int mid=(l+r)>>1;
cdq2(l,mid,k);
cdq2(mid+1,r,k);
sort(eve+l,eve+mid+1,cmpxy);
sort(eve+mid+1,eve+r+1,cmpxy);
int i=r,j=mid;
while(j>=l)
{
while(i>=mid+1 && eve[i].x>=eve[j].x)
{
if (eve[i].f==k)
BIT::add(eve[i].y,nxt[eve[i].idx]);
i--;
}
if (eve[j].f==k-1)
nxt[eve[j].idx]+=BIT::sum(eve[j].y,icnt);
j--;
}
for(int j=r;j>i;j--)
if (eve[j].f==k)
BIT::clr(eve[j].y);
}

int main()
{
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<=n;i++)
read(h[i]),read(v[i]),sx[++icnt]=h[i],sx[++icnt]=v[i];
reverse(h+1,h+n+1); reverse(v+1,v+n+1);
sort(sx+1,sx+icnt+1);
icnt=unique(sx+1,sx+icnt+1)-sx-1;
CDQ::Solve();
BIT::init(icnt);
for (int i=1;i<=n;i++) eve[i].f=f[i],eve[i].idx=i,eve[i].x=Bin(h[i]),eve[i].y=Bin(v[i]);
sort(eve+1,eve+n+1,cmpf);
for (int i=1;i<=ans;i++)
L[i]=n+1,R[i]=0;
for (int i=1;i<=n;i++)
L[eve[i].f]=min(L[eve[i].f],i),R[eve[i].f]=max(R[eve[i].f],i);
for (int i=L[1];i<=R[1];i++)
pre[eve[i].idx]=1;
for (int i=2;i<=ans;i++)
{
for (int j=L[i-1];j<=R[i];j++) itmp[j]=eve[j];
sort(eve+L[i-1],eve+R[i]+1,cmpidx);
cdq1(L[i-1],R[i],i);
for (int j=L[i-1];j<=R[i];j++) eve[j]=itmp[j];
}
for (int i=L[ans];i<=R[ans];i++)
nxt[eve[i].idx]=1;
for (int i=ans;i>=2;i--)
{
for (int j=L[i-1];j<=R[i];j++) itmp[j]=eve[j];
sort(eve+L[i-1],eve+R[i]+1,cmpidx);
cdq2(L[i-1],R[i],i);
for (int j=L[i-1];j<=R[i];j++) eve[j]=itmp[j];
}
for (int i=1;i<=n;i++)
if (f[i]==ans)
tot+=pre[i];
tot=0;
for (int i=1;i<=n;i++)
if (f[i]==1)
tot+=nxt[i];
for (int i=n;i;i--)
printf("%.5lf%c",Ans[i]=pre[i]*nxt[i]/tot,i==1?'\n':' ');
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: