BestCoder#86 E / hdu5808 Price List Strike Back

HDU5808题解
本文介绍了一种解决HDU5808问题的有效算法。通过分治策略及动态规划思想,针对一系列购物记录,判断其是否可能出现错误。算法巧妙地利用了预处理得到的中间结果,有效地减少了计算量。

题目链接:hdu5808

题目大意:

在Byteland一共有n家商店,编号依次为1到n。每家商店只会卖一种物品,其中第i家商店的物品单价为vi,且它到Byteasar的家的距离为di。
Byteasar每天都会进行一次购物,第ii天他会选择一个区间[li,ri],并给自己设定一个距离上限ci,然后他会在编号在该区间内每家到自己家的距离不超过ci的商店购买最多一件物品,当然他也可以选择什么都不买。回家之后,Byteasar会把今天购物所花的钱的总数sumi记录在账本上。
Byteasar的数学不好,他可能会把花的钱记错。
请写一个程序,帮助Byteasar判断每条记录是否一定是错的。
注意:记多或者记少都算记错。


题解:

#官方题解

考虑对序列进行分治,设当前分治区间为[l,r],取mid=(l+r)/2,那么所有在[l,mid)的询问和(mid,r]的询问可以递归分治求解,故只需考虑必然经过mid的询问。

设f[i][j]表示考虑了[i,mid],目前选出的物品和为j时,所选商店到家的距离的最大值最小是多少;g[i][j]表示考虑了(mid,i],目前选出的物品和为j时,所选商店到家的距离的最大值最小是多少,f和g都能在O(100(r-l+1))的复杂度内求出。那么对于一个询问,只需要求出min(max(fi,gs−i)),然后和c比较一下大小就好了。

时间复杂度O(100(nlogn+m)+mlogn)。


只能说好机智%%%,根本没有想到算出取得某价值物品的最大距离最小值来判断某一询问是否可行。

对于l==r的,就只能选l,这里的东西,直接一个if就好了。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 21000
#define maxm 151000
#define N 110
#define inf 0x7fffffff

struct node
{
	int l,r,c,sd,ans;
}q[maxm];
int id[maxm],tol[maxm],tor[maxm];
int n,m,v[maxn],d[maxn],f[maxn][N],to[maxm];
int mymin(int x,int y){return (x<y)?x:y;}
int mymax(int x,int y){return (x>y)?x:y;}
inline int read()
{
	int x=0;char c;c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') {x=x*10+(c-'0');c=getchar();}
	return x;
}
void doit(int len,int l,int r)
{
	int i,j,mid=(l+r)>>1;
	for (i=l;i<=r;i++)
	 for (j=0;j<=100;j++) f[i][j]=inf;
	f[mid][0]=f[mid+1][0]=0;
	f[mid][v[mid]]=d[mid];f[mid+1][v[mid+1]]=d[mid+1];
	for (i=mid-1;i>=l;i--)
	  for (j=100;j>=0;j--)
		if (j>=v[i]) f[i][j]=mymin(f[i+1][j],mymax(f[i+1][j-v[i]],d[i]));
		else f[i][j]=f[i+1][j];
	for (i=mid+2;i<=r;i++)
	  for (j=100;j>=0;j--)
		if (j>=v[i]) f[i][j]=mymin(f[i-1][j],mymax(f[i-1][j-v[i]],d[i]));
		else f[i][j]=f[i-1][j];
	for (i=1;i<=len;i++)
	  for (j=0;j<=q[to[i]].sd;j++)
		q[to[i]].ans|=(mymax(f[q[to[i]].l][j],f[q[to[i]].r][q[to[i]].sd-j])<=q[to[i]].c);
}
void solve(int head,int tail,int l,int r)
{
	if (head>tail) return;
	int i,mid=(l+r)/2,lnum=0,rnum=0,mnum=0;
	if (l==r)
	{
		for (i=head;i<=tail;i++)
		 if (v[l]==q[id[i]].sd && d[l]<=q[id[i]].c) q[id[i]].ans|=1;
		return;
	}
	for (i=head;i<=tail;i++)
	{
		if (q[id[i]].r<=mid) tol[++lnum]=id[i];
		else if (q[id[i]].l>mid) tor[++rnum]=id[i];
		else to[++mnum]=id[i];
	}
	if (mnum) doit(mnum,l,r);
	for (i=0;i<lnum;i++) id[head+i]=tol[i+1];
	for (i=0;i<rnum;i++) id[head+lnum+i]=tor[i+1];
	solve(head,head+lnum-1,l,mid);
	solve(head+lnum,head+lnum+rnum-1,mid+1,r);
}
int main()
{
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int T,i;T=read();
	// scanf("%d",&T);
	while (T--)
	{
		n=read();m=read();
		// scanf("%d%d",&n,&m);
		for (i=1;i<=n;i++) v[i]=read();//scanf("%d",&v[i]);
		for (i=1;i<=n;i++) d[i]=read();//scanf("%d",&d[i]);
		for (i=1;i<=m;i++)
		{
			id[i]=i;q[i].ans=0;
			q[i].l=read();q[i].r=read();
			q[i].c=read();q[i].sd=read();
			// scanf("%d%d%d%d",&q[t].l,&q[t].r,&q[t].c,&q[t].sd);
		}
		solve(1,m,1,n);
		for (i=1;i<=m;i++) printf("%d",1-q[i].ans);
		printf("\n");
	}
	return 0;
}


转载于:https://www.cnblogs.com/Euryale-Rose/p/6527812.html

<think> 我们正在讨论的是C++语言中的特性。用户询问的是包含`#include<bits/stdc++.h>`头文件的编程语言是什么。 根据引用[1][2][3][4]的内容,这个头文件是C++特有的,通常被称为“万能头文件”或“综合头文件”。 因此,我们的回答应该明确指出这是C++语言中的用法。 同时,根据引用内容,这个头文件并非C++标准的一部分,但被许多编译器支持(尤其是GCC),常用于竞赛编程中。 注意:引用[3]提到了一些OJ平台的支持情况(如POJ、HDU不支持,但CF、Topcoder支持),但我们无需在回答中详细展开,除非用户特别询问。 回答结构: 1. 直接给出答案:这是C++语言。 2. 简要解释这个头文件的作用(一次性包含多个标准库头文件)。 3. 说明其常见使用场景(竞赛编程)和注意事项(编译时间、可移植性等)。 4. 生成相关问题。 注意:我们不需要重复用户问题中已经包含的引用内容,而是提炼引用中的关键信息来支持我们的答案。 </think> 包含 `#include<bits/stdc++.h>` 综合头文件的编程语言是 **C++**。这是 C++ 语言特有的预编译指令,主要出现在 GNU GCC 编译器环境中。以下是关键说明: ### 核心特性 1. **非标准但广泛支持**: - 属于 GNU GCC 编译器的扩展特性[^1][^3] - 不被 C++ 标准委员会正式认可,但在竞赛编程中广泛应用 2. **"万能头文件"作用**: ```cpp #include <bits/stdc++.h> // 替代多个标准头文件 ``` - 自动包含几乎所有 C++ 标准库头文件(如 `<iostream>`, `<vector>`, `<algorithm>` 等)[^4] - 等价于手动包含数十个独立头文件 3. **典型应用场景**: | 场景 | 适用性 | 原因 | |------|--------|------| | 编程竞赛(Codeforces, LeetCode 等) | ✅ 推荐使用 | 缩短编码时间,避免遗漏头文件[^2] | | 企业级软件开发 | ❌ 不推荐 | 会增加编译时间和最终二进制体积[^3] | | 特定 OJ 平台(POJ, HDU) | ❌ 不支持 | 平台未实现此扩展[^3] | ### 使用示例 ```cpp #include <bits/stdc++.h> // 单行包含所有库 using namespace std; int main() { vector<int> data = {3,1,4,2}; sort(data.begin(), data.end()); // 直接使用算法库 cout << "排序结果: "; for(auto x : data) cout << x << " "; // 输出: 1 2 3 4 return 0; } ``` ### 注意事项 1. **可移植性问题** 部分编译器(如 MSVC)不支持此头文件,需改用标准头文件[^3]: ```cpp #include <iostream> #include <vector> #include <algorithm> // 标准替代方案 ``` 2. **编译效率** 包含未使用的库会导致: - 编译时间增加(约 20-30%) - 最终可执行文件体积膨胀[^3] 3. **学习建议** 初学者应优先学习标准头文件,避免产生依赖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值