BestCoder#86 E / hdu5808 Price List Strike Back
2017-01-16 11:18
344 查看
题目链接: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]
,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;
}
题目大意:
在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]
,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;
}
相关文章推荐
- HDU 5808 BestCoder Round #86 Price List Strike Back (树状数组)
- HDU 5808 Price List Strike Back (cdq 分治)
- HDU 5808 Price List Strike Back(整体二分)
- hdu 5808 Price List Strike Back 分治
- 【HDU5808 BestCoder Round 86E】【时间排序 树状数组计数 bitsetDP 或分治】Price List Strike Back 距离范围、区间范围商店购物 使得价值和恰为m
- HDU 5808 Price List Strike Back
- Hdu 5808 Price List Strike Back(分治,BestCoder Round #86 E)
- HDU5808 Price List Strike Back
- zoj 2317 Nice Patterns Strike Back(矩阵乘法)
- STL中list中push_back(对象)保存对象的内部实现
- aidl 中通过RemoteCallbackList 运用到的回调机制: service回调activity的方法
- std::list.pop_back() 弹空了列表导致的崩溃
- QP:price list 安全性设置
- list::push_back 错误
- HDU 5804 Price List(水~)
- HDU5804 BestCoder Round 86A 【Price List】
- ASC1 E Nice Patterns Strike Back
- HDU 5804 Price List (BC#86)
- Educational Codeforces Round 31 B. Japanese Crosswords Strike Back
- C++ list——push_back()与insert()