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

%%% PoPoQQQ :http://blog.csdn.net/popoqqq/article/details/44962711


“第一问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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值