APIO2015题解
分组赛讲课讲了APIO2015的题,于是回去就做完了
稍微写一点题解吧
bzoj4069 逐位处理的简单题,然后就是bool型dp
然后a=1 的时候可以把一位状态干掉
当一维状态单调且是bool型dp时,我们可以用dp表示这一维状态;类似的思想也在bzoj1937出现过
var s:array[..] of int64;
n,a,b,i,j,k,p:longint;
g,c:array[..] of longint;
f:array[..,..] of boolean;
now:int64;
can:boolean; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; begin
readln(n,a,b);
for i:= to n do
begin
read(c[i]);
s[i]:=s[i-]+c[i];
end;
if a= then
begin
for p:= downto do
begin
now:=now or int64() shl int64(p);
g[]:=;
for i:= to n do
g[i]:=n+;
for i:= to n do
for j:= to i do
begin
if (s[i]-s[j-]) and now> then continue; //当前模板是0就不能为1,是1就随意,这里转化一下方便快速匹配
g[i]:=min(g[i],g[j-]+);
end;
if g[n]>b then
now:=now xor int64() shl int64(p);
end;
end
else begin
for p:= downto do
begin
now:=now or int64() shl int64(p);
fillchar(f,sizeof(f),false);
f[,]:=true;
for i:= to n do
for j:= to n do
for k:= to i do
if f[k-,j-] then
begin
f[i,j]:=((s[i]-s[k-]) and now=);
if f[i,j] then break;
end; can:=false;
for i:=a to b do
if f[n,i] then
begin
can:=true;
break;
end;
if not can then now:=now xor int64() shl int64(p);
end;
end;
for p:= downto do
now:=now xor int64() shl int64(p);
writeln(now);
end.
4069
bzoj4070 听说现场直接爆搜就过了,这……
首先每只狗只会往一个方向跳
当pi大的时候,每只狗跳的次数少,直接建图即可
当pi小的时候,每个点向外走的种类很少,建立辅助点即可
经典的分类思想,设定一个K
当pi>k,直接建图,设n个点为(i,0)
然后每个点i再建立k个辅助点(i,1)~(i,k) 代表对应跳跃能力
然后看每条狗,如果pi<=k则连向对应的辅助点
然后每个辅助点连向(i,0),表示通过(i,0)可以停下来换狗
然后跑dijkstra即可
注意k不能太大,因为内存卡得比较紧
然后我又tle了,把pi离散化后就过了……
const inf=;
type node=record
po,next,num:longint;
end;
point=record
loc,num:longint;
end; var h:array[..] of point;
e:array[..] of node;
p,d,wh:array[..] of longint;
v,c,b,f:array[..] of longint;
w:array[..,..] of longint;
r,st,en,size,i,j,tot,t,x,y,n,m,len:longint; procedure add(x,y,z:longint);
begin
inc(len);
e[len].po:=y;
e[len].next:=p[x];
e[len].num:=z;
p[x]:=len;
end; procedure swap(var a,b:point);
var c:point;
begin
c:=a;
a:=b;
b:=c;
end; procedure sift(i:longint);
var j,x,y:longint;
begin
j:=i shl ;
while j<=tot do
begin
if (j<tot) and (h[j].num>h[j+].num) then inc(j);
if h[i].num>h[j].num then
begin
x:=h[i].loc;
y:=h[j].loc;
wh[x]:=j;
wh[y]:=i;
swap(h[i],h[j]);
i:=j;
j:=i shl ;
end
else break;
end;
end; procedure up(i:longint);
var j,x,y:longint;
begin
j:=i shr ;
while j> do
begin
if h[i].num<h[j].num then
begin
x:=h[i].loc;
y:=h[j].loc;
wh[x]:=j;
wh[y]:=i;
swap(h[i],h[j]);
i:=j;
j:=i shr ;
end
else break;
end;
end; begin
readln(n,m);
for i:= to m do
begin
readln(b[i],f[i]);
inc(b[i]);
if i= then st:=b[i];
if i= then en:=b[i];
v[f[i]]:=;
end;
for i:= to n do
if v[i]= then
begin
inc(r);
c[r]:=i;
v[i]:=r;
end; size:=trunc(sqrt(r));
if size> then size:=;
t:=n;
for i:= to size do
begin
for j:= to n do
begin
inc(t);
w[j,i]:=t;
add(t,j,);
end;
for j:= to n-c[i] do
begin
add(w[j,i],w[j+c[i],i],);
add(w[j+c[i],i],w[j,i],);
end;
end; for i:= to m do
if f[i]<=c[size] then
add(b[i],w[b[i],v[f[i]]],)
else begin
j:=;
while true do
begin
if b[i]+f[i]*j>n then break;
add(b[i],b[i]+f[i]*j,j);
inc(j);
end;
j:=;
while true do
begin
if b[i]-f[i]*j<= then break;
add(b[i],b[i]-f[i]*j,j);
inc(j);
end;
end; tot:=;
h[].loc:=st;
h[].num:=;
for i:= to t do
if i<>st then
begin
inc(tot);
h[tot].loc:=i;
h[tot].num:=inf;
d[i]:=inf;
wh[i]:=tot;
end; while tot> do
begin
x:=h[].loc;
if x=en then break;
if h[].num=inf then break;
wh[h[tot].loc]:=;
swap(h[],h[tot]);
dec(tot);
sift();
i:=p[x];
while i<> do
begin
y:=e[i].po;
if d[y]>d[x]+e[i].num then
begin
d[y]:=d[x]+e[i].num;
h[wh[y]].num:=d[y];
up(wh[y]);
end;
i:=e[i].next;
end;
end;
if d[en]=inf then writeln(-)
else writeln(d[en]);
end.
4070
bzoj4071 一开始看题的时候想到的是三分套三分……好像听说也能过……
我们只需要考虑起点终点在两侧的
当k=1 大家都会是中位数贪心
当k=2 分类讨论,设第一座桥在S1,第二座桥在S2
不难得到,xi+yi<S1+S2时走S1,否则走S2
这样只要对x+y排序,枚举分割点,分别对两部分求中位数即可然后在求和即可
这我们可以用权值线段树维护
顺便在UOJ上交被叉掉了,没事卡什么快排真是了……
type node=record
x,y,s:longint;
end;
point=record
s:longint;
sum:int64;
end; var c,a:array[..] of longint;
b:array[..] of node;
tree:array[..*,..] of point;
x,y,n,t,mid,m,i,k:longint;
ans,s:int64;
ch1,ch2:char; procedure min(var a:int64; b:int64);
begin
if a>b then a:=b;
end; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; procedure sort(l,r:longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ];
repeat
while a[i]<x do inc(i);
while x<a[j] do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; procedure qsort(l,r:longint);
var i,j,x:longint;
y:node;
begin
i:=l;
j:=r;
x:=b[(l+r) shr ].s;
repeat
while b[i].s<x do inc(i);
while x<b[j].s do dec(j);
if not(i>j) then
begin
y:=b[i]; b[i]:=b[j]; b[j]:=y;
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end; function find(l,r,x:longint):longint;
var m:longint;
begin
while l<=r do
begin
m:=(l+r) shr ;
if c[m]=x then exit(m);
if c[m]>x then r:=m- else l:=m+;
end;
end; procedure add(i,l,r,w,x,y:longint);
var m:longint;
begin
inc(tree[i,w].s,y);
inc(tree[i,w].sum,y*c[x]);
if l<>r then
begin
m:=(l+r) shr ;
if x<=m then add(i*,l,m,w,x,y)
else add(i*+,m+,r,w,x,y);
end;
end; function get(i,l,r,w,k:longint):int64;
var m:longint;
begin
if l=r then exit(int64(k)*int64(c[l]))
else begin
m:=(l+r) shr ;
if tree[i*,w].s>=k then exit(get(i*,l,m,w,k))
else exit(tree[i*,w].sum+get(i*+,m+,r,w,k-tree[i*,w].s));
end;
end; function sum(w,n:longint):int64;
begin
exit(tree[,w].sum-*get(,,m,w,n shr ));
end; begin
readln(k,n);
for i:= to n do
begin
read(ch1);
read(x);
read(ch2); read(ch2);
readln(y);
if ch1=ch2 then s:=s+abs(x-y)
else begin
inc(t);
b[t].x:=x;
b[t].y:=y;
b[t].s:=x+y;
end;
end;
n:=t;
t:=;
for i:= to n do
begin
inc(t);
a[t]:=b[i].x;
inc(t);
a[t]:=b[i].y;
end;
sort(,t);
if k= then
begin
x:=a[(t+) shr ];
ans:=;
for i:= to t do
ans:=ans+abs(x-a[i]);
end
else begin
qsort(,n);
m:=;
c[]:=a[];
for i:= to t do
if a[i]<>a[i-] then
begin
inc(m);
c[m]:=a[i];
end;
mid:=a[t shr ];
for i:= to n do
ans:=ans+abs(b[i].x-mid)+abs(b[i].y-mid);
for i:= to n do
begin
b[i].x:=find(,m,b[i].x);
b[i].y:=find(,m,b[i].y);
add(,,m,,b[i].x,);
add(,,m,,b[i].y,);
end;
for i:= to n do
begin
add(,,m,,b[i].x,);
add(,,m,,b[i].y,);
add(,,m,,b[i].x,-);
add(,,m,,b[i].y,-);
min(ans,sum(,i*)+sum(,t-i*));
end;
end;
writeln(ans+s+n);
end.
4071
APIO2015题解的更多相关文章
- 【题解】P3645 [APIO2015]雅加达的摩天楼(分层图最短路)
[题解]P3645 [APIO2015]雅加达的摩天楼(分层图最短路) 感觉分层图是个很灵活的东西 直接连边的话,边数是\(O(n^2)\)的过不去 然而我们有一个优化的办法,可以建一个新图\(G=( ...
- 题解【luoguP3644 [APIO2015]八邻旁之桥】
题目链接 题解 家和公司在同侧 简单,直接预处理掉 若 \(k=1\) 取所有的居民的\(\frac{家坐标+公司坐标}{2}\)的所有坐标的正中间建一座桥,使所有居民到的距离最小. 实现方法:线段树 ...
- APIO2015简要题解
这场比赛当初是67(?)反正就是Cu滚粗了…… 先给个题目的传送门:http://wenku.baidu.com/link?url=mUxdsYomenU-e9SFVPacVtXysemiQA4KnP ...
- BZOJ4071 & 洛谷3644 & UOJ112:[APIO2015]巴邻旁之桥——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4071 https://www.luogu.org/problemnew/show/P3644 ht ...
- 贪心(qwq)习题题解
贪心(qwq)习题题解 SCOI 题解 [ SCOI2016 美味 ] 假设已经确定了前i位,那么答案ans一定属于一个区间. 从高位往低位贪心,每次区间查找是否存在使此位答案为1的值. 比如6位数确 ...
- 【BZOJ4071】[Apio2015]巴邻旁之桥 Treap
[BZOJ4071][Apio2015]巴邻旁之桥 Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 ...
- 【BZOJ4069】[Apio2015]巴厘岛的雕塑 按位贪心+DP
[BZOJ4069][Apio2015]巴厘岛的雕塑 Description 印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道. 在这条主干道上一共有 N 座雕塑,为方便起见,我们把这些雕塑从 ...
- 【BZOJ4070】[Apio2015]雅加达的摩天楼 set+最短路
[BZOJ4070][Apio2015]雅加达的摩天楼 Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼 ...
- Luogu P3646 [APIO2015]巴厘岛的雕塑
深夜写题解系列,话说这题暑假的时候就在LOJ上做掉了,然后今天看到Luogu上有就去交了一下,发现没写过题解,赶紧来补一下 说句题外话APIO2015的题目好水啊 首先考虑按位取或的过程,很显然要从二 ...
随机推荐
- LintCode-Word Segmentation
Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separa ...
- Notes of the scrum meeting(2013/10/27)
软工项目组buaa_smile确定自由项目主题及实现功能的scrum meeting meeting time:1:00~2:00p.m.,October 27th,2013 meeting plac ...
- JDBC 学习笔记(二)—— 大数据+存储过程+批处理+事务管理
本文目录: 1.使用JDBC处理大数据 2.使用JDBC处理大文本 3.使用JDBC处理二进制数据 4.Oracle中大数据处理 5 ...
- dbutils报错:com.microsoft.sqlserver.jdbc.SQLServerException: 无法识别元数据的表
今天用dbutils操作数据库,莫名地报错:com.microsoft.sqlserver.jdbc.SQLServerException: 无法识别元数据的表 检查了sql语句没有问题.经过仔细排查 ...
- python爬取某些网站出错的解决办法
用urllib2.urlopen方法打开糗事百科的网站,http://www.qiushibaike.com/,发现会失败,网上百度,说可能是服务器端对爬虫做了屏蔽,需要伪装header头部信息,下面 ...
- 中国餐馆过程(CRP)
查如何事先确定聚类簇数目发现的,是对狄利克雷过程的(DP)的一种解释. 假设一个中国餐馆有无限的桌子,第一个顾客到来之后坐在第一张桌子上.第二个顾客来到可以选择坐在第一张桌子上,也可以选择坐在一张新的 ...
- [设计模式] 12 代理模式 proxy
在GOF的<设计模式:可复用面向对象软件的基础>一书中对代理模式是这样说的:为其他对象提供一种代理以控制对这个对象的访问.结合上面的游戏代理的例子和下面的图,我们来进行分析一下.以前你是这 ...
- Kafka之Purgatory Redesign Proposal (翻译)
Purgatory是Kafka server中处理请求时使用的一个重要的数据结构.正好研究ReplicaManager源码的时候发现了这篇文章,顺便翻译下.由于这个proposal里的很多东西需要看源 ...
- Proxmox虚拟机增加硬盘容量
1.首先在虚拟机控制台选择调整硬盘容量,弹出窗口为增加的容量 2.重启虚拟机,用fdisk –l查看新增容量是否被识别 3.用cfdisk创建分区,分区格式为Primary 8e (Linux LVM ...
- DiskGenius的 “终止位置参数溢出”错误解决方法。
(转帖)同事电脑系统启动突然明显变慢,重装系统后问题仍未解决(windowsxp sp3).帮忙分析感觉是磁盘分区表出现了错误,用通用PE工具箱进入PE系统,DiskGenius工具检查:“终止位置参 ...