题目链接

BZOJ2800

题解

区间加极难操作,差分之后可转化为两点一加一减

那么现在问题就将每个点暂时独立开来

先判定每个点是否被\((A,B)\)整除,否则无解

之后我们先将\(A,B\)化为互质,所有数除一个\((A,B)\)

求得

\[Ax + By = 1
\]

那么对于点\(d[i]\),满足

\[d[i] = A(xd[i] + kB) + B(yd[i] - kA)
\]

其中\(k\)可以取任意值

我们对于单点的目标,是最小化

\[|xd[i] + kB|+|yd[i] - kA|
\]

两个绝对值相加是一个单峰函数,利用三分法即可得出\(k\)

从而得到每个点目前最优解\(X[i] = xd[i] + kB,Y[i] = yd[i] - kA\)

但是我们做到了单个点最优,但整体不一定合法,我们必须满足正负操作次数相同

\[A\sum\limits_{i = 1}^{n}X[i] + B\sum\limits_{i = 1}^{n}Y[i] = 0
\]

而由于\(\sum d[i] = 0\)

故我们只需保证\(T = \sum X[i] = 0\)

显然我们只需改变\(\frac{T}{B}\)次

对于每个\(X[i]\)我们计算出它改变一次的代价,用一个堆维护即可

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#define REP(i,n) for (register int i = 1; i <= (n); i++)
#define cls(s) memset(s,0,sizeof(s))
#define LL long long int
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
struct pr{LL v,i;};
inline bool operator <(const pr& a,const pr& b){
return a.v > b.v;
}
priority_queue<pr> q;
LL n,A,B,X,Y,d[maxn],h[maxn],xx[maxn],yy[maxn],dd;
void exgcd(LL a,LL b,LL& d,LL& x,LL& y){
if (!b){d = a; x = 1; y = 0;}
else exgcd(b,a % b,d,y,x),y -= (a / b) * x;
}
inline LL cost(int i,LL k){
return abs(X * d[i] + k * B) + abs(Y * d[i] - k * A);
}
void workmin(){
REP(i,n){
LL l = -INF,r = INF,lmid,rmid,L,R,K;
while (r - l >= 3){
lmid = (l + l + r) / 3;
rmid = (r + l + r) / 3;
L = cost(i,lmid);
R = cost(i,rmid);
if (L == R){
if (cost(i,lmid - 1) < L) r = rmid;
else l = lmid;
}
else if (L > R) l = lmid;
else r = rmid;
}
K = l;
for (int j = l + 1; j <= r; j++)
if (cost(i,j) < cost(i,K)) K = j;
xx[i] = X * d[i] + K * B;
yy[i] = Y * d[i] - K * A;
}
}
inline LL price(int i){
return abs(yy[i] - dd * A) + abs(xx[i] + dd * B) - abs(xx[i]) - abs(yy[i]);
}
void print(){
//REP(i,n) printf("(%lld,%lld)\n",xx[i],yy[i]); puts("");
LL ans = 0;
REP(i,n) ans += abs(xx[i]) + abs(yy[i]);
printf("%lld\n",ans >> 1);
}
void workok(){
LL sum = 0;
REP(i,n) sum += xx[i];
sum /= B;
dd = sum > 0 ? -1 : 1; sum = abs(sum);
REP(i,n) q.push((pr){price(i),i});
pr u;
while (sum--){
u = q.top(); q.pop();
xx[u.i] += dd * B;
yy[u.i] -= dd * A;
q.push((pr){price(u.i),u.i});
}
}
int main(){
n = read(); A = read(); B = read(); LL D;
exgcd(A,B,D,X,Y); A /= D; B /= D;
REP(i,n){
h[i] = read();
if (h[i] % D){puts("-1"); return 0;}
h[i] /= D; d[i] = h[i] - h[i - 1];
}
n++;
d[n] = -h[n - 1];
workmin();
workok();
print();
return 0;
}

BZOJ2800 [Poi2012]Leveling Ground 【扩展欧几里得 + 三分 + 堆】的更多相关文章

  1. [zoj3593]扩展欧几里得+三分

    题意:给一个数A,有6种操作,+a,-a,+b,-b,+(a+b),-(a+b),每次选择一种,用最少的次数变成B. 思路:由于不同的操作先后顺序对最后的结果没有影响,并且加一个数与减一个相同的数不能 ...

  2. Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C.Ray Tracing (模拟或扩展欧几里得)

    http://codeforces.com/contest/724/problem/C 题目大意: 在一个n*m的盒子里,从(0,0)射出一条每秒位移为(1,1)的射线,遵从反射定律,给出k个点,求射 ...

  3. UVA 12169 Disgruntled Judge 枚举+扩展欧几里得

    题目大意:有3个整数 x[1], a, b 满足递推式x[i]=(a*x[i-1]+b)mod 10001.由这个递推式计算出了长度为2T的数列,现在要求输入x[1],x[3],......x[2T- ...

  4. UVA 10090 Marbles 扩展欧几里得

    来源:http://www.cnblogs.com/zxhl/p/5106678.html 大致题意:给你n个球,给你两种盒子.第一种盒子每个盒子c1美元,可以恰好装n1个球:第二种盒子每个盒子c2元 ...

  5. POJ 1061 青蛙的约会 扩展欧几里得

    扩展欧几里得模板套一下就A了,不过要注意刚好整除的时候,代码中有注释 #include <iostream> #include <cstdio> #include <cs ...

  6. 【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

    Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到C ...

  7. poj 2891 扩展欧几里得迭代解同余方程组

    Reference: http://www.cnblogs.com/ka200812/archive/2011/09/02/2164404.html 之前说过中国剩余定理传统解法的条件是m[i]两两互 ...

  8. poj 2142 扩展欧几里得解ax+by=c

    原题实际上就是求方程a*x+b*y=d的一个特解,要求这个特解满足|x|+|y|最小 套模式+一点YY就行了 总结一下这类问题的解法: 对于方程ax+by=c 设tm=gcd(a,b) 先用扩展欧几里 ...

  9. poj 1061 扩展欧几里得解同余方程(求最小非负整数解)

    题目可以转化成求关于t的同余方程的最小非负数解: x+m*t≡y+n*t (mod L) 该方程又可以转化成: k*L+(n-m)*t=x-y 利用扩展欧几里得可以解决这个问题: eg:对于方程ax+ ...

随机推荐

  1. Python常用模块之PIL(手册篇:Image模块)

    官方手册地址:http://effbot.org/imagingbook/image.htm  Image模块 图像模块提供了一个具有相同名称的类,用于表示一个PIL的图像.该模块还提供了许多功能,包 ...

  2. 数据库之python操作mysql

    目录 一.pymysql 二.SQLAchemy 2.操作使用 (1)连接数据库 (2)执行原生SQL语句 (3)ORM操作-数据表操作 (4)ORM操作-数据行操作 (5)更多例子 一.pymysq ...

  3. xml配置文件特殊符号的处理方法

    2017.7.19遇到问题:偶然出现“认证失败,请重新登录”的现象   在xml中英文问号“?”是可以被正常解析的,但是以下这几种符号是不能正常解析的:分别是“&”.“<”.“>” ...

  4. MySQL原生API、MySQLi面向过程、MySQLi面向对象、PDO操作MySQL

    [转载]http://www.cnblogs.com/52fhy/p/5352304.html 本文将举详细例子向大家展示PHP是如何使用MySQL原生API.MySQLi面向过程.MySQLi面向对 ...

  5. Daily Scrumming* 2015.10.29(Day 10)

    一.总体情况总结 二.今明两天任务表 Member Today’s Task Tomorrow’s Task 江昊 了解微信API,与社团服务平台创业公司嗨社团创始人沟通,了解其平台运营方案与商业模式 ...

  6. 20135313-exp1

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计 班级:1353 姓名:吴子怡 学号:20135313 成绩:            指导教师:娄嘉鹏  实 ...

  7. JavaScript实现弹出层(以layer.open为例)

    首先,引用layer,自行下载. 添加如下两行 <script src=" ../layer/jquery.min.js"></script> <sc ...

  8. Android笔记-2-TextView的属性详解

    [Android 基础]TextView的属性详解 android:autoLink :设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接.可选值(none/web / ...

  9. Results the mutual for the first time(alpha阶段总结)

    由于前天听大家的成果展时,做得笔记不够完善,有一两个组找不到信息,如果没有评到的组望谅解. 分数分配: 由于组内某些原因,我们现重新分组: 试用版: 总结前阶段的工作: 在前一段时间,我们第一个spr ...

  10. Think In Java读书笔记:内部类覆盖及其初始化

    本文相关章节:第十章 内部类 10.10 内部类可以被覆盖吗 在读至本节第二个范例代码时(及下方的代码),我对输出结果中的第一个“Egg.Yolk()”很不理解,为什么它会第一个地方输出. 我起初认为 ...