zoukankan      html  css  js  c++  java
  • BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷
    (O(n^2))DP很好写,对于当前的i从之前满足条件的j中选一个最大值,(dp[i]=d[j]+1)

     for(int j=1; j<i; ++j)
    	if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次 
    		dp[i]=max{dp[j]+1};
    

    转移要满足两个条件:(a[j]<=minv[i] && maxv[j]<=a[i])
    一个二维偏序问题,CDQ、树套树都可以。
    (minv[x])(a[y])作为两个坐标轴,(dp[j])表示其上一点((A[j],maxv[j])).
    这样就成了一个二维平面,可以向其中插入一些点dp[i],询问一个矩形区域(也是一段前缀)中某点最大值
    线段树套线段树 树状数组套线段树都可做 复杂度(O(nlog^2n))
    后者时间还可以
    树状数组套线段树:

    //企图二维树状数组 但动态开点的话 中间一段没有的区间会中断y方向的Query..
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define gc() getchar()
    #define now node[rt]
    #define lson l,m,node[rt].ls
    #define rson m+1,r,node[rt].rs
    #define lb(x) ((x)&-(x))
    const int N=1e5+5;
    
    int n,m,A[N],minv[N],maxv[N],MaxV,MaxA;
    namespace Tree_2D
    {
    	struct Seg_Tree
    	{
    		struct Node
    		{
    			int maxv,ls,rs;
    		}node[N<<6];//还要再小点。。不然BZOJ上依旧MLE 
    		inline int new_Node()
    		{
    			static int cnt=0;
    			return ++cnt;
    		}
    		void Insert(int l,int r,int &rt,int p,int v)
    		{
    			if(!rt) rt = new_Node();
    			now.maxv = std::max(now.maxv, v);
    			if(l<r)
    			{
    				int m=l+r>>1;
    				if(p<=m) Insert(lson,p,v);
    				else Insert(rson,p,v);
    			}
    		}
    		int Query(int l,int r,int rt,int L,int R)
    		{
    			if(!rt) return 0;
    			if(L<=l && r<=R) return now.maxv;
    			int m=l+r>>1;
    			if(L<=m)
    				if(m<R) return std::max(Query(lson,L,R),Query(rson,L,R));
    				else return Query(lson,L,R);
    			return Query(rson,L,R);
    		}
    	}t;
    	struct Bit
    	{
    		int root[N];
    		void Insert(int p,int y,int v)
    		{
    			while(p<=MaxV)
    				t.Insert(1,MaxA,root[p],y,v), p+=lb(p);
    		}
    		int Query(int p,int y)
    		{
    			int res=0;
    			while(p)
    				res=std::max(res,t.Query(1,MaxA,root[p],1,y)), p-=lb(p);
    			return res;
    		}
    	}t2D;
    }
    #undef now
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    
    int main()
    {
    	n=read(),m=read();
    	for(int i=1; i<=n; ++i)
    		maxv[i]=minv[i]=A[i]=read(), MaxA=std::max(MaxA,A[i]);
    	for(int x,y,i=1; i<=m; ++i)
    		x=read(), y=read(), maxv[x]=std::max(maxv[x],y), minv[x]=std::min(minv[x],y);
    	for(int i=1; i<=n; ++i) MaxV=std::max(MaxV,maxv[i]);
    	int ans=0;
    	for(int v,i=1; i<=n; ++i)
    	{
    		v = Tree_2D::t2D.Query(minv[i],A[i]) + 1;
    		Tree_2D::t2D.Insert(A[i],maxv[i],v);
    		ans=std::max(ans,v);
    	}
    	printf("%d",ans);
    
    	return 0;
    }
    

    二维线段树:

    /*
    BZOJ上直接MLE...洛谷P4093 4508ms(比Bit套Segtree慢3倍+) 293.33MB 
    空间消耗比较大 写指针吧。。
    */
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define gc() getchar()
    #define lson l,m,rt->ls
    #define rson m+1,r,rt->rs
    const int N=1e5+5;
    
    int n,m,A[N],maxv[N],minv[N],MaxA,MaxV;
    namespace Seg_Tree2D
    {
    	struct Node
    	{
    		int maxv;
    		Node *ls,*rs;
    		Node(): maxv(0),ls(NULL),rs(NULL) { }
    	}pool[N<<7];//(logN)^2=256(2^8) 开得小点吧要不空间会炸 
    	struct Node2D
    	{
    		Node *root;
    		Node2D *ls,*rs;
    		Node2D(): root(NULL),ls(NULL),rs(NULL) { }
    	}pool2D[N<<1],*root;
    	inline Node *new_Node()
    	{
    		static int cnt=0;
    		return &pool[cnt++];
    	}
    	inline Node2D *new_Node2D()
    	{
    		static int cnt=0;
    		return &pool2D[cnt++];
    	}
    	Node2D *Build(int l,int r)
    	{
    		Node2D *rt = new_Node2D();
    		if(l<r)
    		{
    			int m=l+r>>1;
    			rt->ls = Build(l,m);
    			rt->rs = Build(m+1,r);
    		}
    		return rt;
    	}
    	int Query(int l,int r,Node *rt,int L,int R)
    	{
    		if(!rt) return 0;
    		if(L<=l && r<=R) return rt->maxv;
    		int m=l+r>>1;
    		if(L<=m)
    			if(m<R) return std::max(Query(lson,L,R),Query(rson,L,R));
    			else return Query(lson,L,R);
    		return Query(rson,L,R);
    	}
    	int Query2D(int l,int r,Node2D *rt,int L,int R,int y1,int y2)
    	{
    		if(L<=l && r<=R) return Query(1,MaxA,rt->root,y1,y2);
    		int m=l+r>>1;
    		if(L<=m)
    			if(m<R) return std::max(Query2D(lson,L,R,y1,y2),Query2D(rson,L,R,y1,y2));
    			else return Query2D(lson,L,R,y1,y2);
    		return Query2D(rson,L,R,y1,y2);
    	}
    	void Insert(int l,int r,Node *&rt,int p,int v)
    	{
    		if(!rt) rt = new_Node();//!
    		rt->maxv = std::max(rt->maxv, v);
    		if(l<r)
    		{
    			int m=l+r>>1;
    			if(p<=m) Insert(lson,p,v);
    			else Insert(rson,p,v);
    		}
    	}
    	void Insert2D(int l,int r,Node2D *rt,int p,int y,int v)
    	{
    		Insert(1, MaxA, rt->root, y, v);
    		if(l<r)
    		{
    			int m=l+r>>1;
    			if(p<=m) Insert2D(lson,p,y,v);
    			else Insert2D(rson,p,y,v);
    		}
    	}
    	void Init()
    	{
    		root = Build(1,MaxV);
    	}
    	int Query_Max(int l,int r,int y1,int y2)
    	{
    		return Query2D(1,MaxV,root,l,r,y1,y2);
    	}
    	void Insert_Node(int x,int y,int v)
    	{
    		Insert2D(1,MaxV,root,x,y,v);
    	}
    }
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-'0',c=gc());
    	return now;
    }
    
    
    int main()
    {
    	n=read(),m=read();
    	for(int i=1; i<=n; ++i)
    		maxv[i]=minv[i]=A[i]=read(), MaxA=std::max(MaxA,A[i]);
    	for(int x,y,i=1; i<=m; ++i)
    		x=read(), y=read(), maxv[x]=std::max(maxv[x],y), minv[x]=std::min(minv[x],y);
    	for(int i=1; i<=n; ++i) MaxV=std::max(MaxV,maxv[i]);
    	Seg_Tree2D::Init();
    	int ans=0;
    	for(int v,i=1; i<=n; ++i)
    	{
    		v = Seg_Tree2D::Query_Max(1,minv[i],1,A[i]) + 1;
    		Seg_Tree2D::Insert_Node(A[i],maxv[i],v);
    		ans=std::max(ans,v);
    	}
    	printf("%d",ans);
    
    	return 0;
    }
    
  • 相关阅读:
    Solr的学习使用之(五)添加索引数据
    django视图层
    django的路由层
    第九章 MySQL 高可用(MHA)
    第八章 mysql的主从复制
    第七章 mysql的备份与恢复
    第六章 mysql日志
    第五章 存储引擎
    第四章 元数据 索引
    第三章 mysql 数据库接口程序以及SQL语句操作
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8440693.html
Copyright © 2011-2022 走看看