首页 > 其他分享 >CF500F New Year Shopping

CF500F New Year Shopping

时间:2022-12-14 21:56:02浏览次数:78  
标签:tmp Shopping CF500F int num 20001 New include dp

链接:https://www.luogu.com.cn/problem/CF500F
这题有两种做法:

\(1\).可将物品线段树分治,这样可以通过

\(2\).可将原序列每隔\(p\)格分块,然后像回滚莫队那样处理每一个以块端点为端点的询问,然后每一个询问可以被拆成两部分,将它们合并即可.

这里给第\(2\)种.

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#define N 20000
using namespace std;
struct node
{
	int c,h,t;
};
struct fix
{
	int num,dp[8001];
	bool operator < (const fix &a)const
	{
		return num<a.num; 
	}
};
struct Query
{
	int num,x,y;
	bool operator < (const Query &a)const
	{
		return x<a.x;
	}
};
fix Q[4001],Q2[4001],tmp;
Query query[40001];
vector<node>P[20001];
node happy[20001];
int p,n,q,block[20001],ans[20001],length,length2;
int read()
{
	char c=0;
	int sum=0;
	while (c<'0'||c>'9')
		c=getchar();
	while ('0'<=c&&c<='9')
	{
		sum=sum*10+c-'0';
		c=getchar();
	}
	return sum;
}
void adder(int x)
{
	for (int i=0;i<P[x].size();++i)
		for (int j=4000;j>=P[x][i].c;--j)
			tmp.dp[j]=max(tmp.dp[j],tmp.dp[j-P[x][i].c]+P[x][i].h);
	for (int j=1;j<=4000;++j)
		tmp.dp[j]=max(tmp.dp[j],tmp.dp[j-1]);
	return;	
}
int main()
{
	n=read(),p=read();
	for (int i=1;i<=N;++i)
		block[i]=(i-1)/p+1;
	for (int i=1;i<=n;++i)
	{
		happy[i].c=read(),happy[i].h=read(),happy[i].t=read();
		P[happy[i].t].push_back(happy[i]);
	}
	sort(query+1,query+q+1);
	for (int i=block[N];i>=1;--i)
	{
		for (int j=1;j<=4000;++j)
			tmp.dp[j]=0;
		for (int j=min(i*p,N);j>=(i-1)*p+1;--j)
		{
			adder(j);
			if (P[j].size())
			{
				Q[++length]=tmp;
				Q[length].num=j;
			}
		}
		for (int j=1;j<=4000;++j)
			tmp.dp[j]=0;
		for (int j=(i-1)*p+1;j<=min(i*p,N);++j)
		{
			adder(j);
			if (P[j].size())
			{
				Q2[++length2]=tmp;
				Q2[length2].num=j;
			}
		}
	}
	sort(Q+1,Q+length+1);
	sort(Q2+1,Q2+length2+1);
	for (int j=1;j<=4000;++j)
		Q[0].dp[j]=Q2[0].dp[j]=0;
	int x,y,res=0,s1,s2;
	q=read();
	for (int i=1;i<=q;++i)
	{
		x=read(),y=read();
		res=s1=s2=0;
		for (int j=1;j<=length;++j)
			if (max(x-p+1,0)<=Q[j].num)
			{
				s1=j;
				break;
			}
		if (Q[s1].num>min(block[max(x-p+1,0)]*p,N))
			s1=0;
		for (int j=length2;j>=1;--j)
			if (x>=Q2[j].num)
			{ 
				s2=j;
				break;
			}
		if (Q[s2].num<(block[x]-1)*p+1)
			s2=0;
		if (block[max(x-p+1,0)]==block[x])
			s2=0;
		for (int j=0;j<=y;++j)
			res=max(res,Q[s1].dp[j]+Q2[s2].dp[y-j]);
		printf("%d\n",res);
	}
	return 0;
}

标签:tmp,Shopping,CF500F,int,num,20001,New,include,dp
From: https://www.cnblogs.com/zhouhuanyi/p/16983706.html

相关文章