ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

《简单DP》

2022-06-30 22:36:49  阅读:150  来源: 互联网

标签:date1 date2 int Tree mid DP 简单 dp


简单DP

「JOISC 2020 Day4」治疗计划

首先考虑问题的维度\([治疗状态],[时间],[花费]\)

治疗状态肯定无法省去

时间其实可以忽略,因为最终的答案的可行性与时间无关,但可能会加大转移的难度

事实上时间是可以不入状态的

考虑用01串表示治疗状态,但其实可以直接用前缀治疗状态

设\(dp[i]\)表示\([1,i]\)已治好的最小花费

\(111100111\),类似的情况,因为是连续的区间,所以不会出现》

转换一下,设\(dp[i]\)表示第\(i\)个计划实施后\([1,r_i]\)已被治疗

\(dp[i]=dp[j]+c[i],(r_j-l_i+1\geq|t_i-t_j|)\)

解释一下,首先对于\(i\)找到一个\(j\)使得\([1,r_i]\)被覆盖,要保证\([1,r_j]\)被感染到\(l_i\)之前被及时治疗

最初我觉得有可能有第三个计划将\(l_i-1\)及时覆盖使得dp的条件放宽

但事实上这种方案可以归纳到第三个计划的更新

这样做是\(O(n^2)\)的

考虑优化,每一\(dp_i\)是由当前满足条件最小\(dp_j\)更新

类似与\(dijkstra\),可以用当前最小更新,模型为无向图,没有顺序,因为尽管线性\(dp\)按\(r_i\)排序,但\(r_i\)大的一定不会更新小的

将上式绝对值裁开,可以得到两个不等式

\[r_j-t_j+1\geq l_i-t_i(t_i<t_j) \\ r_j+t_j+1\geq l_i+t_i(t_i\geq t_j) \]

用线段树维护最小,以\(t_i\)排序建树,树上查找后设为无穷,复杂度均摊\(O(nlog_2(n))\)

#include<bits/stdc++.h>
#define int long long
#define INF 1e14
#define ls 2*p
#define rs 2*p+1
using namespace std;
const int MAXM=1e5+5;
int n,m;
struct Task{
	int t,l,r,c;
	bool operator<(const Task x)const{
		return t<x.t;
	}
}a[MAXM];
int dp[MAXM];
struct node{
	int val,u;
	bool operator<(const node x)const{
		return val>x.val;
	}
}; 
priority_queue<node>q;
struct Seg{
	int l,r;
	int date1;
	int date2;
}Tree[MAXM*4];
void push_up(int p)
{
	Tree[p].date1=min(Tree[ls].date1,Tree[rs].date1);
	Tree[p].date2=min(Tree[ls].date2,Tree[rs].date2);
}
void Build(int p,int l,int r)
{
	Tree[p].l=l;
	Tree[p].r=r;
	if(l==r)
	{
		Tree[p].date1=a[l].l+a[l].t;
		Tree[p].date2=a[l].l-a[l].t;
		return;
	}
	int mid=(l+r)>>1;
	Build(ls,l,mid);
	Build(rs,mid+1,r);
	push_up(p);
}
void Update(int p,int k)
{
	if(Tree[p].l==Tree[p].r)
	{
		Tree[p].date1=INF;
		Tree[p].date2=INF;
		return;
	 } 
	 int mid=(Tree[p].l+Tree[p].r)>>1;
	if(k<=mid)
	{
		Update(ls,k);
	}
	else
	{
		Update(rs,k);
	}
	push_up(p);
}
vector<int>avail;
void FindL(int p,int k1,int k2)
{
	if(Tree[p].l==Tree[p].r)
	{
	//	printf("%d %d&**\n",k2,Tree[p].date2);
		if(Tree[p].date1<=k2)
		{
			avail.push_back(Tree[p].l);
		}
		
		return;
	}
	int mid=(Tree[p].l+Tree[p].r)>>1;
	if(mid>=k1)
	{
		if(Tree[ls].date1<=k2)
		{
			FindL(ls,k1,k2);
		}
		if(Tree[rs].date1<=k2)
		{
			FindL(rs,k1,k2);
		}
	}
	else
	{
		if(Tree[rs].date1<=k2)
		{
			FindL(rs,k1,k2);
		}
	}
}

void FindR(int p,int k1,int k2)
{
	if(Tree[p].l==Tree[p].r)
	{
		//printf("%d %d&**\n",k2,Tree[p].date2);
		if(Tree[p].date2<=k2)
		{
			avail.push_back(Tree[p].l);
		}
		
		return;
	}
	int mid=(Tree[p].l+Tree[p].r)>>1;
	if(mid<k1)
	{
		if(Tree[ls].date2<=k2)
		{
			FindR(ls,k1,k2);
		}
		if(Tree[rs].date2<=k2)
		{
			FindR(rs,k1,k2);
		}
	}
	else
	{
		if(Tree[ls].date2<=k2)
		{
			FindR(ls,k1,k2);
		}
	}
}
signed main()
{
//	freopen("01-01.in","r",stdin);
	memset(dp,0x3f,sizeof(dp));
	scanf("%lld %lld",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld %lld %lld %lld",&a[i].t,&a[i].l,&a[i].r,&a[i].c);
	}
	
	sort(a+1,a+1+m);
	Build(1,1,m);
	for(int i=1;i<=m;i++)
	{
		if(a[i].l==1)
		{
	//		printf("%d %d-\n",i,a[i].c);
			node sf;
			sf.u=i;
			sf.val=a[i].c;
			dp[i]=a[i].c;
			q.push(sf);
			Update(1,i);
		}
	}
	int tot=0;
	while(q.size())
	{
		
		node temp=q.top();
	//	printf("%lld %lld--\n",temp.u,temp.val);
		q.pop();
		if(a[temp.u].r==n)
		{
			printf("%lld",temp.val);
			return 0;
		}
		avail.clear();
		FindL(1,temp.u,a[temp.u].r+a[temp.u].t+1);
		for(int i=0;i<avail.size();i++)
		{
			int vv=avail[i];
			dp[vv]=dp[temp.u]+a[vv].c;
			Update(1,vv);
			node fgf;
			fgf.u=vv;
			fgf.val=dp[vv];
			q.push(fgf);
	//		printf("%d %d\n",vv,dp[vv]);
		}
	//	printf("\n");
		avail.clear();
		FindR(1,temp.u,a[temp.u].r-a[temp.u].t+1);
		for(int i=0;i<avail.size();i++)
		{
			int vv=avail[i];
			dp[vv]=dp[temp.u]+a[vv].c;
			Update(1,vv);
			node fgf;
			fgf.u=vv;
			fgf.val=dp[vv];
			q.push(fgf);
	//		printf("%d %d\n",vv,dp[vv]);
		}
	//	++tot;
	//	printf("%d\n",tot);
	}
	printf("-1");
	
}

标签:date1,date2,int,Tree,mid,DP,简单,dp
来源: https://www.cnblogs.com/kid-magic/p/16428842.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有