zoukankan      html  css  js  c++  java
  • [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
    ",i,f[i].f,f[i].g);
    	}
    	if(!f[n].g)puts("NIE");
    	else printf("%d %d
    ",f[n].f,f[n].g);
    	return 0;
    }
    
  • 相关阅读:
    Android SDK上手指南1:应用程序结构
    【转】kalman滤波
    VHDL学习笔记——数字系统设计
    VHDL基础 学习笔记
    Windows命令行(DOS命令)教程
    PHP-内嵌式语言(转)(未看)
    Java并发编程的艺术笔记(三)——Thread.join()
    Java并发编程的艺术笔记(二)——wait/notify机制
    Java并发编程的艺术笔记(一)——volatile和syncronized关键字
    Java虚拟机JVM详解
  • 原文地址:https://www.cnblogs.com/xzz_233/p/10732574.html
Copyright © 2011-2022 走看看