bzoj2800
这题好难,翻了一下波兰文的题解……这好像是当年唯一没人A的题目
首先区间修改不难想到差分,我们令d1=x1,dn+1=-xn,di=xi-xi-1
注意Σdi=0,这样对于[l,r]的修改(比如+a) 就是d[l]+a d[r+1]-a
首先不难想到,对于每个di,ax+by=di一定要有解(gcd(a,b)|di)
这样我们知道这个方程的解为xi=x0+kb yi=y0-ka (x0,y0为这个方程一组解,可以由扩展欧几里德得到)
现在我们考虑最终的答案要求是Σxi=0 Σyi=0且(|Σxi|+|Σyi|)/2最小
我们有这样一个思路,先求出每个f(i)=|xi|+|yi|的最小值,最后总体贪心,调整成Σxi=0 Σyi=0
f(i)=|x0+kb|+|y0-ka|这显然是凸函数,我们可以用三分来解决
注意ax0+by0=di Σdi=0,所以我们只要Σki=0就满足Σxi=0 Σyi=0
设当前s=|Σki|,我们只要用堆调整s次即可得到满足条件的最优值
(关于s的规模不大会证,但跑得很快是了)
type node=record
loc:longint;
num:int64;
end; var h:array[..] of node;
x,y:array[..] of int64;
d:array[..] of longint;
g,i,j,a,b,n,x0,y0:longint;
ans,l,m,r,s:int64; procedure swap(var a,b:int64);
var c:int64;
begin
c:=a;
a:=b;
b:=c;
end; function gcd(a,b:longint):longint;
begin
if b= then exit(a)
else exit(gcd(b,a mod b));
end; function cal(x,y,k:int64):int64;
begin
exit(abs(x+k*int64(b))+abs(y-k*int64(a)));
end; procedure exgcd(a,b:longint; var x,y:longint);
var xx,yy:longint;
begin
if b= then
begin
x:=;
y:=;
end
else begin
exgcd(b,a mod b,x,y);
xx:=x;
yy:=y;
x:=yy;
y:=xx-a div b*yy;
end;
end; procedure sift(i:longint);
var j:longint;
x:node;
begin
j:=i shl ;
while j<=n do
begin
if (j<n) and (h[j].num>h[j+].num) then inc(j);
if h[i].num>h[j].num then
begin
x:=h[i]; h[i]:=h[j]; h[j]:=x;
i:=j;
j:=j shl ;
end
else break;
end;
end; begin
readln(n,a,b);
g:=gcd(a,b);
for i:= to n do
begin
read(d[i]);
if d[i] mod g<> then
begin
writeln(-);
halt;
end;
d[i]:=d[i] div g;
end;
a:=a div g; b:=b div g;
d[n+]:=-d[n];
for i:=n downto do
d[i]:=d[i]-d[i-];
inc(n);
if a=b then
begin
for i:= to n do
ans:=ans+abs(d[i]);
writeln(ans div );
halt;
end;
exgcd(a,b,x0,y0);
for i:= to n do
begin
x[i]:=int64(x0)*int64(d[i]);
y[i]:=int64(y0)*int64(d[i]);
// writeln(x[i],' ',y[i],' ',d[i],':');
l:=-d[i];
r:=d[i];
if l>r then swap(l,r);
while l+<r do
begin
m:=(r-l+) div ;
if cal(x[i],y[i],l+m)>cal(x[i],y[i],l+*m) then l:=l+m+
else r:=l+*m-;
end;
if cal(x[i],y[i],l)>cal(x[i],y[i],r) then
begin
x[i]:=x[i]+r*int64(b);
y[i]:=y[i]-r*int64(a);
s:=s+r;
end
else begin
x[i]:=x[i]+l*int64(b);
y[i]:=y[i]-l*int64(a);
s:=s+l;
end;
// writeln(x[i],' ',y[i],' ',i,' ',d[i]);
end;
if s< then
begin
for i:= to n do
swap(x[i],y[i]);
g:=a; a:=b; b:=g;
s:=abs(s);
end;
for i:= to n do
begin
h[i].loc:=i;
h[i].num:=abs(x[i]-b)+abs(y[i]+a)-abs(x[i])-abs(y[i]);
end;
for i:=n div downto do
sift(i); for i:= to s do
begin
j:=h[].loc;
x[j]:=x[j]-b;
y[j]:=y[j]+a;
h[].num:=abs(x[j]-b)+abs(y[j]+a)-abs(x[j])-abs(y[j]);
sift();
end;
for i:= to n do
ans:=ans+abs(x[i])+abs(y[i]);
writeln(ans div );
end.
bzoj2800的更多相关文章
- BZOJ2800 [Poi2012]Leveling Ground 【扩展欧几里得 + 三分 + 堆】
题目链接 BZOJ2800 题解 区间加极难操作,差分之后可转化为两点一加一减 那么现在问题就将每个点暂时独立开来 先判定每个点是否被\((A,B)\)整除,否则无解 之后我们先将\(A,B\)化为互 ...
- POI2012题解
POI2012题解 这次的完整的\(17\)道题哟. [BZOJ2788][Poi2012]Festival 很显然可以差分约束建图.这里问的是变量最多有多少种不同的取值. 我们知道,在同一个强连通分 ...
随机推荐
- java集合类(三)About Iterator & Vector(Stack)
接上篇:java集合类学习(二) Talk about “Iterator”: 任何容器类,在插入元素后,还需要取回元素,因为这是容器的最基本工作.对于一般的容器,插入有add()相关方法(List, ...
- ffmpeg 音频转码
大多数厂家摄像机输出的音频流格式都是PCM,有一些场合(比如讲音视频流保存成Ts流)需要将PCM格式转成AAC格式.基本的思路是先解码得到音频帧,再将音频帧编码成AAC格式.编码和解码之间需要添加一个 ...
- C#的配置文件App.config使用总结 - 转
http://blog.csdn.net/celte/article/details/9749389 首先,先说明,我使用的app.config 配置文件的格式如下: <?xml version ...
- C# Winform 拖放操作
http://www.cnblogs.com/imlions/p/3189773.html 在开发程序的时候,为了提高用户的使用体验,或满足相关用户的功能,总是离不开拖放功能.而本文是总结winfor ...
- 【BZOJ】【1086】 【SCOI2005】王室联邦
树分块 orz vfk && PoPoQQQ http://vfleaking.blog.163.com/blog/static/174807634201231684436977/ h ...
- ASP.NET WebAPI2 发布之后404 Note Found
方法一:首先确保服务器安装.Net FrameWork 4.0 并且注册IIS 如果先安装.net framework4.0,再安装IIS,则会出现4.0的ISAPI没有注册的情况. 运行:C:\Wi ...
- uva 10313
递推 参考了别人的解法 dp[i][j] 表示价值为i用j个硬币可以有多少种方法 dp[j][k] += dp[j-i][k-1] 意思是多加一枚价值为i的硬币,加上价值为j-i用k-1个硬币的总 ...
- spring mvc 数据绑定总结
spring mvc 做web开发时,经常会不知道如何合适绑定页面数据.用惯struts2的朋友更认为spring mvc 绑定数据不如struts2方便(本人最开始也是这么认为),经过一段时间的应用 ...
- uniqueidentifier 数据类型(转)
想要产生这种唯一标识的格式的数据: 6F9619FF-8B86-D011-B42D-00C04FC964FF 应该怎么做呢?答: uniqueidentifier 数据类型可存储 16 字节的二进制 ...
- java基础知识回顾之---java String final类普通方法的应用之“按照字节截取字符串”
/*需求:在java中,字符串“abcd”与字符串“ab你好”的长度是一样,都是四个字符.但对应的字节数不同,一个汉字占两个字节.定义一个方法,按照最大的字节数来取子串.如:对于“ab你好”,如果取三 ...