[PA2014]Druzyny

[PA2014]Druzyny


暴力水过纪念

暴力是显然的dp \(f[i]\)表示以i结尾最多的段以及方案数,转移就枚举当前i所在这一段的左端点check一下。

然后神猫说了一个暴力 dp的时候在线段树上搜索 然后可以直接判这一段是否都满足/都不满足(其实这个判断是假的放缩不等式之后可能判不掉),如果一定都满足就直接用这一段更新,都不满足就返回。

然后bzoj数据挂了?

我又加了两个剪枝就过了:

如果当前的f最大值比需要更新的f小就返回

线段树先递归f值较大的儿子

就ac了。。。水水水

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 1000000007
il int gi(){
	int x=0,f=0;char ch=getchar();
	while(!isdigit(ch))f^=ch=='-',ch=getchar();
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return f?-x:x;
}
int c[1000010],d[1000010];
il int max(const int&a,const int&b){return a>b?a:b;}
il int min(const int&a,const int&b){return a<b?a:b;}
struct state{int f,g;};
il state operator+(const state&a,const state&b){
	if(a.f>b.f)return a;
	if(a.f<b.f)return b;
	return(state){a.f,(a.g+b.g)%mod};
}
state f[1000010],segf[4000010];
int cn[4000010],cx[4000010],dx[4000010],dn[4000010];
#define mid ((l+r)>>1)
il vd update(int x,int l,int r,const int&p){
	if(l==r){segf[x]=f[p-1];cx[x]=cn[x]=c[l],dx[x]=dn[x]=d[l];return;}
	if(p<=mid)update(x<<1,l,mid,p);
	else update(x<<1|1,mid+1,r,p);
	segf[x]=segf[x<<1]+segf[x<<1|1];
	cx[x]=std::max(cx[x<<1],cx[x<<1|1]);
	dx[x]=std::max(dx[x<<1],dx[x<<1|1]);
	cn[x]=std::min(cn[x<<1],cn[x<<1|1]);
	dn[x]=std::min(dn[x<<1],dn[x<<1|1]);
}
il vd query(int x,int l,int r,const int&p,int cxr,int dnr){
	if(l>p)return;
	if(r<=p){
		if(segf[x].f<f[p].f)return;
		if(max(cn[x],cxr)>p-l+1)return;
		if(min(dx[x],dnr)<p-r+1)return;
		if(max(cx[x],cxr)<=p-r+1&&min(dn[x],dnr)>=p-l+1){f[p]=f[p]+segf[x];return;}
	}
	if(segf[x<<1].f>segf[x<<1|1].f)query(x<<1,l,mid,p,std::max(cxr,cx[x<<1|1]),std::min(dnr,dn[x<<1|1])),query(x<<1|1,mid+1,r,p,cxr,dnr);
	else query(x<<1|1,mid+1,r,p,cxr,dnr),query(x<<1,l,mid,p,std::max(cxr,cx[x<<1|1]),std::min(dnr,dn[x<<1|1]));
}
#undef mid
int main(){
#ifndef ONLINE_JUDGE
	freopen("C.in","r",stdin);
	freopen("C.out","w",stdout);
#endif
	int n=gi();
	for(int i=1;i<=n;++i)c[i]=gi(),d[i]=gi();
	for(int i=1;i<=n<<2;++i)cx[i]=dx[i]=-1e9,cn[i]=dn[i]=1e9;
	f[0].g=1;update(1,1,n,1);
	for(int i=1;i<=n;++i){
		f[i].f=-1e9;
		query(1,1,n,i,-1e9,1e9);
		++f[i].f;
		if(i!=n)update(1,1,n,i+1);
		//printf("%d %d %d\n",i,f[i].f,f[i].g);
	}
	if(!f[n].g)puts("NIE");
	else printf("%d %d\n",f[n].f,f[n].g);
	return 0;
}
posted @ 2019-04-18 21:34  菜狗xzz  阅读(235)  评论(0编辑  收藏  举报