zoukankan      html  css  js  c++  java
  • 省选模拟赛 4.26 T1 dp 线段树优化dp

    LINK:T1

    avatar
    avatar

    算是一道中档题 考试的时候脑残了 不仅没写优化 连暴力都打挂了。

    容易发现一个性质 那就是同一格子不会被两种以上的颜色染。(颜色就三种.

    通过这个性质就可以进行dp了.先按照左端点排序。

    设f[i]表示前i个画笔必选的最大价值。

    枚举决策j 分类讨论相交还是包含 还是相离。

    其中包含的情况没必要讨论 相交需要比对一下颜色再进行转移 不过我写的时候多打一个东西导致爆零.

    值得一提的是 对于相交的情况 相交的部分不会被之前转移的线段给交上去 可以证明这样不是最优的。

    所以这样dp是正确的。

    code:

    const int MAXN=100010;
    int n,m,s1,s2,flag;
    ll ans,f[MAXN];
    struct wy{int x,y,c;}t[MAXN];
    inline int cmp(wy a,wy b){return a.x<b.x;}
    int main()
    {
    	freopen("T1.in","r",stdin);
    	freopen("T1.out","w",stdout);
    	get(n);get(m);get(s1);get(s2);
    	rep(1,m,i)
    	{
    		int get(c),get(x),get(y);
    		t[i]=(wy){x,y,c};
    		if(!flag)flag=c;
    		else if(flag!=c)flag=INF;
    	}
    	sort(t+1,t+1+m,cmp);
    	if(flag!=INF)
    	{
    		ll ans=0;int mx=0;
    		rep(1,m,i)
    		{
    			if(mx>=t[i].y)continue;
    			if(t[i].x<mx)ans+=((ll)t[i].y-mx)*s1;
    			else ans+=(ll)((ll)t[i].y-t[i].x+1)*s1;
    			mx=t[i].y;
    		}
    		putl(ans);
    		return 0;
    	}
    	//putl(ans);
    	if(m<=1000)
    	{
    		rep(1,m,i)
    		{
    			rep(0,i-1,j)
    			{
    				if(t[i].y<=t[j].y)continue;
    				if(t[i].x>t[j].y)
    				{
    					f[i]=max(f[i],f[j]+((ll)t[i].y-t[i].x+1)*s1);
    					continue;
    				}
    				int ww=(t[i].c!=t[j].c);
    				f[i]=max(f[i],f[j]+((ll)t[i].y-t[j].y)*s1-((ll)t[j].y-t[i].x+1)*ww*(s1+s2));
    			}
    			ans=max(ans,f[i]);
    		}
    		putl(ans);return 0;
    	}
    	return 0;
    }
    

    考虑正解。其实正解很好想 不过我没胆子写。

    容易 发现可以分类讨论。对于相离的情况 写一个线段树 在右端点放值 查询查左端点-1即可。

    对于相交的情况 还是分类讨论 考虑如果是同颜色的话查 还是右端点放值 区间内查 放值的具体形式展开上述的dp式即可。

    对于不同颜色相交 同样展开上述dp式 在线段树里做即可。

    第一种情况需要一颗线段树 第二种情况需要三颗线段树 第三种情况同样需要三种 简单的做法是 三种不同颜色各自维护相交的情况。

    由于所有的线段树维护的东西相同 所以可以使用指针做这件事情 也可以使用结构体。

    const int MAXN=100010;
    int n,m,top;ll s1,s2;
    int b[MAXN<<1];
    struct wy{int x,y,c;}t[MAXN];
    inline int cmp(wy a,wy b){return a.x<b.x;}
    struct jl
    {
    	ll s[MAXN<<3];
    	inline void cle(){memset(s,0xcf,sizeof(s));}
    	inline void change(int p,int l,int r,int w,ll x)
    	{
    		if(l==r){s[p]=max(s[p],x);return;}
    		int mid=(l+r)>>1;
    		if(w<=mid)change(zz,l,mid,w,x);
    		else change(yy,mid+1,r,w,x);
    		s[p]=max(s[zz],s[yy]);
    	}
    	ll ask(int p,int l,int r,int L,int R)
    	{
    		if(L<=l&&R>=r)return s[p];
    		int mid=(l+r)>>1;
    		if(R<=mid)return ask(zz,l,mid,L,R);
    		if(L>mid)return ask(yy,mid+1,r,L,R);
    		return max(ask(zz,l,mid,L,R),ask(yy,mid+1,r,L,R));
    	}
    }f[3],g[3],s;
    int main()
    {
    	freopen("1.in","r",stdin);
    	//freopen("T1.out","w",stdout);
    	get(n);get(m);get(s1);get(s2);
    	rep(1,m,i)
    	{
    		int get(c),get(x),get(y);
    		t[i]=(wy){x,y,c-1};
    		b[++top]=x;b[++top]=y;
    	}
    	sort(b+1,b+1+top);
    	int num=0;
    	rep(1,top,i)if(i==1||b[i]!=b[i-1])b[++num]=b[i];
    	rep(1,m,i)
    	{	
    		t[i].x=lower_bound(b+1,b+1+num,t[i].x)-b;
    		t[i].y=lower_bound(b+1,b+1+num,t[i].y)-b;
    	}
    	sort(t+1,t+1+m,cmp);
    	s.cle();
    	rep(0,2,i)f[i].cle(),g[i].cle();
    	s.change(1,0,num,0,0);
    	rep(1,m,i)
    	{
    		ll ww=s.ask(1,0,num,0,t[i].x-1)+(b[t[i].y]-b[t[i].x]+1)*s1;
    		rep(0,2,j)
    		{
    			if(t[i].c==j)//同色转移用f
    			ww=max(ww,f[j].ask(1,0,num,t[i].x,t[i].y)+b[t[i].y]*s1);
    			else //不同色用g
    			ww=max(ww,g[j].ask(1,0,num,t[i].x,t[i].y)+b[t[i].x]*(s1+s2)-s1-s2+b[t[i].y]*s1);
    		}
    		s.change(1,0,num,t[i].y,ww);
    		f[t[i].c].change(1,0,num,t[i].y,ww-b[t[i].y]*s1);
    		g[t[i].c].change(1,0,num,t[i].y,ww-b[t[i].y]*(s1+s1+s2));
    	}
    	putl(s.s[1]);
    	return 0;
    }
    
  • 相关阅读:
    Leetcode 283. Move Zeroes
    利用脚本,一键设置java环境变量(默认安装路径)
    'wmic' 不是内部或外部命令,也不是可运行的程序 解决方法
    PowerShell因为在此系统中禁止执行脚本解决方法
    使用VBSCRIPT安装字体
    批处理基本知识以及进阶 V2.0
    Vbs 脚本编程简明教程之一
    用批处理,批量安装字体文件 (Erector.bat)
    windows 7 系统装机优化
    使用批处理替换windows系统中的hosts文件
  • 原文地址:https://www.cnblogs.com/chdy/p/12780595.html
Copyright © 2011-2022 走看看