bzoj1835: [ZJOI2010]base 基站选址
新的一年新的开始。结果第一题就用了几乎一周。而且感觉很不好。
先检讨自己。最近写的各种数据结构模板基本没打过出来,各种细节崩盘,这题线段树都居然被lazy标记没清零卡挂。
DP还是博大精深,这东西感觉没学好啊。
---------------------------------------
很容易想DP的。主要是怎么D,一开始我的想法是f[i][j]表示到第1~i个点被覆盖,建了j个站。但是这题的覆盖是关于当前点的,什么意思,就是可能k1点在k2点前面,但k1受到了很后面的k3覆盖不用补偿,而k2却要,这样就gg。
那改一下,f[i][j]表示在第i个点建站,建了j个。DP方程就是这样的。
f[i][j]=max(f[i][j],f[k][j-1]+(k~x中没被覆盖的点的w和))+c[i];
而这个时间复杂度O(n^2*k)必挂。
膜了题解才发现,这题是一道经典的线段树维护DP,线段树负责区间修改和区间查询。时间复杂度就可以降到O(nlogn*k)
显然维护的就是f[k][j]+(k~x中没被覆盖的点的w和),按照1~k下标即可。
那么难点在于(k~x中没被覆盖的点的w和)
考虑四个点k,p,x,x+1
k表示被继承点,x、x+1可以继承k(当然还有其他,方便起见就不罗列了)
那么对于k和x,若x继承k,那么k、x之间肯定没有点建站,那么f[k][j-1]+(k~x中没被覆盖的点的w和)假设已经预处理了,再假设x这个站建下来,x覆盖了p,并且p和x的距离就是p能被影响的最远距离
然后对于x+1的话,如果x+1要继承k,那么p必定没有覆盖,因为x已经是最远的点了,x+1无论如何也覆盖不了。
由此,我们二分预处理出一个点往后最远可以影响到它的点,然后用邻接表把最远距离相等的点记录,那么当枚举x到x+1的时候,就可以快速把那些与p情况一样的点的w加上就行了。
那么还有一个问题,k也可以覆盖到后面的点呀,假如x+1覆盖不了,但k覆盖得了,那也不应该把w加上。
解决方法是再二分预处理出一个点往前最远可以影响到它的点,当区间修改的时候,就修改那些在它前面的,影响不到它的点,这些点就是1~L[x]-1
PS:实际的操作中j没必要留一维。当j-1的信息记入线段树中时,f就没用了,直接在上面更新
还有就是n++,m++,在最后多弄一个d=inf,c=0,s=0,的结束点,由于s=0,所以m++的那个站肯定建在n+1位置,又由于d=inf,不影响其他原来的点,此举旨在将最后答案确定到n+1位置方便取最大,因为对于这个问题,建站不一定要建在n位置,同时判断前面的位置能否覆盖后面也很麻烦。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int inf=; int n,m;
int d[],c[],w[];
int L[],R[];//表示最远可以影响到当前点的位置
LL f[]; struct line
{
int to,next;
}l[];int llen,last[];
void ins(int x,int y)
{
llen++;l[llen].to=y;
l[llen].next=last[x];last[x]=llen;
} int fhj(int k)
{
int l=,r=n,ret;
while(l<=r)
{
int mid=(l+r)/;
if(d[mid]>=k)r=mid-, ret=mid;
else l=mid+;
}
return ret;
}
int fqq(int k)
{
int l=,r=n,ret;
while(l<=r)
{
int mid=(l+r)/;
if(k>=d[mid])l=mid+, ret=mid;
else r=mid-;
}
return ret;
}
void sc()
{
scanf("%d%d",&n,&m);n++;m++;
llen=;memset(last,,sizeof(last)); d[]=;
for(int i=;i<n;i++)scanf("%d",&d[i]);
d[n]=inf;
for(int i=;i<n;i++)scanf("%d",&c[i]);
c[n]=;
int x;
for(int i=;i<n;i++)
scanf("%d",&x), L[i]=fhj(d[i]-x), R[i]=fqq(d[i]+x), ins(R[i],i);
L[n]=n;R[n]=n;
for(int i=;i<n;i++)scanf("%d",&w[i]); } //----------sc---------------------- struct seq
{
int l,r,lc,rc;LL c,lazy;
}tr[];int trlen;
void bt(int l,int r)
{
trlen++;int now=trlen;
tr[now].l=l;tr[now].r=r;
tr[now].c=;tr[now].lazy=;
tr[now].lc=tr[now].rc=-;
if(l<r)
{
int mid=(l+r)/;
tr[now].lc=trlen+;bt(l,mid);
tr[now].rc=trlen+;bt(mid+,r);
tr[now].c=min(tr[tr[now].lc].c,tr[tr[now].rc].c);
}
else tr[now].c=f[l];
}
LL findmin(int now,int l,int r)
{
if(tr[now].l==l&&tr[now].r==r){return tr[now].c;}
int lc=tr[now].lc,rc=tr[now].rc;
int mid=(tr[now].l+tr[now].r)/; if(tr[now].lazy!=)
{
tr[lc].c+=tr[now].lazy;
tr[rc].c+=tr[now].lazy;
tr[lc].lazy+=tr[now].lazy;
tr[rc].lazy+=tr[now].lazy;
tr[now].lazy=;
} if(r<=mid)return findmin(lc,l,r);
else if(mid+<=l)return findmin(rc,l,r);
else return min(findmin(lc,l,mid),findmin(rc,mid+,r));
}
void change(int now,int l,int r,int k)
{
if(l>r)return ;
if(tr[now].l==l&&tr[now].r==r){tr[now].c+=k;tr[now].lazy+=k;return ;}
int lc=tr[now].lc,rc=tr[now].rc;
int mid=(tr[now].l+tr[now].r)/; if(tr[now].lazy!=)
{
tr[lc].c+=tr[now].lazy;
tr[rc].c+=tr[now].lazy;
tr[lc].lazy+=tr[now].lazy;
tr[rc].lazy+=tr[now].lazy;
tr[now].lazy=;
} if(r<=mid)change(lc,l,r,k);
else if(mid+<=l)change(rc,l,r,k);
else change(lc,l,mid,k), change(rc,mid+,r,k); tr[now].c=min(tr[lc].c,tr[rc].c);
} //-------seq---------------- int main()
{
freopen("base.in","r",stdin);
freopen("base.out","w",stdout);
sc(); int tre=;
for(int i=;i<=n;i++)
{
f[i]=tre+c[i];
for(int k=last[i];k;k=l[k].next)
{
int to=l[k].to;
tre+=w[to];
}
}
//yu j=1
LL ans=f[n];
for(int j=;j<=m;j++)
{
trlen=;bt(,n);
for(int i=j;i<=n;i++)
{
f[i]=findmin(,j-,i-)+c[i];
for(int k=last[i];k;k=l[k].next)
{
int to=l[k].to;
change(,,L[to]-,w[to]);
}
}
ans=min(ans,f[n]);
}
printf("%lld\n",ans);
return ;
}
bzoj1835: [ZJOI2010]base 基站选址的更多相关文章
- bzoj1835[ZJOI2010]base基站选址
据说正解是什么线段树优化DP,但是作为脑子有坑选手,我们需要5k的做法: 主席树+决策单调性..... F[m][i]表示已经放置了m个基站,第m个基站放置在第i个村庄,第i个村庄及之前的村庄的总最少 ...
- BZOJ1835: [ZJOI2010]base 基站选址【线段树优化DP】
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- BZOJ1835: [ZJOI2010]base 基站选址(线段树优化Dp)
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- 2018.11.06 bzoj1835: [ZJOI2010]base 基站选址(线段树优化dp)
传送门 二分出每个点不需要付www贡献的范围,然后可以推出转移式子: f[i][j]=f[i−1][k]+value(k+1,j)+c[i]f[i][j]=f[i-1][k]+value(k+1,j) ...
- 【BZOJ1835】[ZJOI2010]base 基站选址 线段树+DP
[BZOJ1835][ZJOI2010]base 基站选址 Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯 ...
- BZOJ 1835: [ZJOI2010]base 基站选址 [序列DP 线段树]
1835: [ZJOI2010]base 基站选址 题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立 ...
- bzoj 1835: [ZJOI2010]base 基站选址
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- bzoj 1835 [ZJOI2010]base 基站选址(DP+线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1835 [题意] 有n个村庄,每个村庄位于d[i],要求建立不多于k个基站,在第i个村庄 ...
- BZOJ 1835 [ZJOI2010]base 基站选址:线段树优化dp
传送门 题意 有 $ n $ 个村庄在一排直线上,现在要建造不超过 $ K $ 个通讯基站,基站只能造在村庄处. 第 $ i $ 个村庄距离第 $ 1 $ 个村庄的距离为 $ D_i $ .在此建造基 ...
随机推荐
- 洛谷 P1156 垃圾陷阱 谈论剪枝,非满分
这是一个91分的非dp代码(是我太弱) 剪枝八五个(实际上根本没那么多,主要是上课装逼,没想到他们dp水过去了),不过我的思路与dp不同: 1.层数到达i+1,return 这个必须有 2.当前剩余生 ...
- luogu2869 [USACO07DEC]美食的食草动物Gourmet Grazers
先满足挑剔的 #include <algorithm> #include <iostream> #include <cstdlib> #include <cs ...
- python019 Python3 File(文件) 方法
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数: 序号 方法及描述 1 file.close() 关闭文件.关闭后文件不能再进行读写操作. 2 file.flush() ...
- POJ-2421Constructing Roads,又是最小生成树,和第八届河南省赛的引水工程惊人的相似,并查集与最小生成树的灵活与能用,水过~~~
Constructing Roads Time Limit: 2000MS Memory Limit: 65536K Description There are N v ...
- 【转】关于大型网站技术演进的思考(十九)--网站静态化处理—web前端优化—上(11)
网站静态化处理这个系列马上就要结束了,今天我要讲讲本系列最后一个重要的主题web前端优化.在开始谈论本主题之前,我想问大家一个问题,网站静态化处理技术到底是应该归属于web服务端的技术范畴还是应该归属 ...
- 七牛云赵之健:多维度融合赋能视频 AI 的实践
6 月 30 日下午,赵之健在七牛架构师实践日第二十九期进行了<多维度融合赋能视频 AI 的实践>为题的实战分享. 作者简介: 赵之健,七牛人工智能实验室资深算法工程师, 七 ...
- 洛谷P1276 校门外的树(增强版)未完工
题目描述 校门外马路上本来从编号0到L,每一编号的位置都有1棵树.有砍树者每次从编号A到B处连续砍掉每1棵树,就连树苗也不放过(记 0 A B ,含A和B):幸运的是还有植树者每次从编号C到D 中凡是 ...
- 飞扬的小鸟(codevs 3729)
题目描述 Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画面右方的管道缝隙.如果小鸟一不小心撞到了水管或者掉在地上的话,便 ...
- php的错误控制运算符
php的错误控制运算符 PHP中提供了一个错误控制运算符“@”. 可以将@放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉: 如果开启了php.ini 中的 track_error ...
- flex里InputText不能输入中文
最近做项目都没做任何的更新,今天突然遇到在flex里的InputText无法进行中文输入,晚上查找了下资料,很多原因说是flashplayer的一个BUG. 在网上找到两种解决办法: 1.会出现这种情 ...