Description:

https://gmoj.net/senior/#main/show/4611

题解:

先把A从大到小排序,最小的由排序不等式显然。

考虑类似第k短路的A*的做法。

定义状态为一个已经确定的前缀,它自己的代价显然,它的估价函数为把剩下的数字从小到大填的代价。

以自己代价+估价函数代价放入堆里一直扩展下一个即可,队列中会有\(n^2k\)个,加上求代价的复杂度,时间复杂度:\(O(n^3k)\)。

考虑优化扩展,注意假设要在下一位放数字,肯定是从小到大放,所以优化这个无用的扩展,可以减小一个n。

再考虑,一个状态一直放最小的到长度为n为止,这中间经过了很多状态,考虑把这些也优化了,

对状态重新定义为已知道了\(p[1..n]\)的值,前\(t-1\)个固定了,第\(t\)个可以变大,第\(t\)个现在是第\(w\)大,\(bz[t+1..n-1]\)表示\(p[x]\)能不能和\(p[x+1]\)交换。

发现状态只有\(O(k)\)个了,时间复杂度:\(O(nk)\)。

用可持久化线段树维护即可做到\(O(n~log~n+k~log~n)\)

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std; const ll inf = 1e18; const int N = 2e5 + 5; int n, k; ll a[N]; int cmpa(int x, int y) {
return x > y;
} ll sum; #define i0 t[i].l
#define i1 t[i].r #define pii pair<ll, int>
#define fs first
#define se second struct tree {
int l, r, p;
bool ban, lz;
pii x, y;
} t[N * 100]; int tt; void upd(int i) {
t[i].x = min(t[i0].x, t[i1].x);
t[i].y = min(t[i0].y, t[i1].y);
} void bt(int &i, int x, int y) {
i = ++ tt;
if(x == y) {
t[i].p = x;
t[i].x = t[i].y = pii(a[x] - a[x + 1], x);
return;
}
int m = x + y >> 1;
bt(i0, x, m); bt(i1, m + 1, y);
upd(i);
} int pl, pr, px, py, pz; void dgp(int &i, int x, int y) {
if(x == y) { px = t[i].p; return;}
int m = x + y >> 1;
if(pl <= m) dgp(i0, x, m); else dgp(i1, m + 1, y);
}
int fp(int &i, int x) {
pl = pr = x;
dgp(i, 1, n);
return px;
} void kq(int &i) {
if(i) {
t[++ tt] = t[i]; i = tt;
t[i].ban = 0;
t[i].lz = 1;
t[i].x = t[i].y;
}
}
void down(int &i) {
if(t[i].lz) {
kq(i0), kq(i1);
t[i].lz = 0;
}
} void dd(int &i, int x, int y) {
if(y < pl || x > pr) return;
t[++ tt] = t[i], i = tt;
if(x == y) {
t[i].y.fs += (ll) px * (a[x] - a[x + 1]);
if(t[i].ban) t[i].x = pii(inf, x); else
t[i].x = t[i].y;
if(py) t[i].p = pz;
return;
}
int m = x + y >> 1; down(i);
dd(i0, x, m); dd(i1, m + 1, y);
upd(i);
}
void xiu(int &i, int x, int y) {
int v = fp(i, x);
if(x > 1) {
py = 0;
pl = pr = x - 1, px = y - v;
dd(i, 1, n);
}
py = 1; pz = y;
pl = pr = x, px = v - y;
// pp("xiu %d %d %d %d\n", x, y, v, px);
dd(i, 1, n);
} void du(int &i, int x, int y) {
if(y < pl || x > pr) return;
t[++ tt] = t[i], i = tt;
if(x == y) {
t[i].ban = 1;
t[i].x = pii(inf, x);
return;
}
int m = x + y >> 1; down(i);
du(i0, x, m); du(i1, m + 1, y);
upd(i);
}
void jz(int &i, int x) {
pl = pr = x;
du(i, 1, n);
} void ddq(int &i, int x, int y) {
if(y < pl || x > pr) return;
if(x == y) {
px = t[i].ban; return;
}
int m = x + y >> 1; down(i);
ddq(i0, x, m); ddq(i1, m + 1, y);
}
int qry_ban(int &i, int x) {
pl = pr = x;
ddq(i, 1, n);
return px;
} pii pu; void ft(int &i, int x, int y) {
if(y < pl || x > pr) return;
if(x >= pl && y <= pr) {
pu = min(pu, t[i].x);
return;
}
int m = x + y >> 1; down(i);
ft(i0, x, m); ft(i1, m + 1, y);
} pii qry(int &i, int t) {
pl = t + 1, pr = n - 1;
pu = pii(inf, 0);
ft(i, 1, n);
return pu;
} int rt; struct nod {
int g, t, w;
pii c;
ll s;
}; bool operator < (nod a, nod b) {
return a.s > b.s;
} priority_queue<nod> q; void build() {
bt(rt, 1, n); nod b;
b.g = rt; b.t = 1; b.w = 2;
b.c = pii(a[1] - a[2], 1);
b.c = min(b.c, qry(b.g, b.t));
b.s = sum;
b.s += b.c.fs; q.push(b);
} void swap(nod &b, int x, int y) {
int v1 = fp(b.g, x), v2 = fp(b.g, y);
// pp(" swap %d %d %d %d\n", x, y, v1, v2);
// pp("%lld\n", qry(b.g, 1).fs);
xiu(b.g, x, v2); xiu(b.g, y, v1);
// pp("%lld\n", qry(b.g, 1).fs);
} int mak(nod &b) {
if(b.w > n) {
b.t ++; b.w = b.t + 1;
if(b.t >= n) return 0;
}
b.c = pii(inf, 0);
if(!qry_ban(b.g, b.t)) {
b.c = pii((a[b.t] - a[b.w]) * (fp(b.g, b.w) - fp(b.g, b.t)), b.t);
}
b.c = min(b.c, qry(b.g, b.t));
if(b.c.fs == inf) return 0; b.s += b.c.fs;
return 1;
} void work(nod b) {
int x = b.c.se, y = x == b.t ? b.w : x + 1;
if(x == b.t) {
nod c = b;
swap(c, x, y);
c.w ++; kq(c.g);
if(mak(c)) q.push(c); b.s -= b.c.fs;
jz(b.g, x);
if(mak(b)) q.push(b);
} else {
nod c = b;
swap(c, x, y);
c.t = x, c.w = x + 2;
kq(c.g);
if(mak(c)) q.push(c); b.s -= b.c.fs;
jz(b.g, x);
if(mak(b)) q.push(b);
}
} int main() {
freopen("water.in", "r", stdin);
freopen("water.out", "w", stdout);
scanf("%d %d", &n, &k);
fo(i, 1, n) scanf("%lld", &a[i]);
sort(a + 1, a + n + 1, cmpa);
fo(i, 1, n) sum += a[i] * i;
build();
pp("%lld\n", sum);
fo(ii, 1, k - 1) {
nod b = q.top(); q.pop();
pp("%lld\n", b.s);
work(b);
// pp("fs = %lld\n", qry(b.g, b.t).fs);
// pp("%d %d %lld %d\n", b.t, b.w, b.c.fs, b.c.se);
// fo(i, 1, n) {
// int x = b.c.se, y = x == b.t ? b.w : x + 1;
// int t = i == x ? y : (i == y ? x : i);
// pp("%d ", fp(b.g, t));
// }
// hh;
}
}

JZOJ 4611. 【NOI2016模拟7.11】接水问题 (贪心+A*+可持久化线段树)的更多相关文章

  1. [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)

    题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...

  2. 【bzoj3524】【Poi2014】【Couriers】可持久化线段树(主席树)水题

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62485671 向大(hei)佬(e)势力学(di ...

  3. 【模拟8.11】将军令(贪心&&树形DP)

    只看45分的话,是树形DP....(当然也有能拿到70分+的大佬) 40分: 只考虑k==1的情况,树形DP 所以每个节点可能被父亲,自己,儿子控制 设f[MAXN][3],0表示儿子,1表示自己,2 ...

  4. 2019.02.11 bzoj1568: [JSOI2008]Blue Mary开公司(线段树)

    传送门 题意简述:维护整体加一条线段,求单点极值. 思路: 直接上李超线段树维护即可. 代码: #include<bits/stdc++.h> #define ri register in ...

  5. 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) ...

  6. 2018.06.27 NOIP模拟 节目(支配树+可持久化线段树)

    题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的 ...

  7. hdu 5475 模拟计算器乘除 (2015上海网赛H题 线段树)

    给出有多少次操作 和MOD 初始值为1 操作1 y 表示乘上y操作2 y 表示除以第 y次操作乘的那个数 线段树的叶子结点i 表示 第i次操作乘的数 将1替换成y遇到操作2 就把第i个结点的值 替换成 ...

  8. [JZOJ6075]【GDOI2019模拟2019.3.20】桥【DP】【线段树】

    Description N,M<=100000,S,T<=1e9 Solution 首先可以感受一下,我们把街道看成一行,那么只有给出的2n个点的纵坐标是有用的,于是我们可以将坐标离散化至 ...

  9. jzoj5986. 【WC2019模拟2019.1.4】立体几何题 (权值线段树)

    传送门 题面 题解 不难看出每个点的大小为行列限制中较小的那一个(因为数据保证有解) 对于行的每个限制,能取到的个数是列里限制大于等于它的数的个数,同理,对于列是行里大于它的个数(这里没有等于,为了避 ...

随机推荐

  1. 让pomelo可以获取到反向代理websockets的真实用户IP

    /node_modules/pomelo/lib/connectors/hybridsocket.js 找到 var Socket = function(id, socket) { 给remoteAd ...

  2. HDU 1233 最小生成树模板题,练练模板

    还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  3. Centos 搭建wordpress个人博客

    1.装apache.mariadb yum install httpd mariadb-server php php-mysql -ysystemctl start httpdsystemctl en ...

  4. 精通awk系列文章

    精通awk系列文章 我录制了两个awk相关的视频教程: Awk经典实战案例精讲 精通awk精品课程:awk从入门到精通 1.安装新版本的gawk 2.本教程测试所用示例文件 3.铺垫知识:读取文件的几 ...

  5. Java——字节和字符的区别

    字节 1.bit=1  二进制数据0或1 2.byte=8bit  1个字节等于8位 存储空间的基本计量单位 3.一个英文字母=1byte=8bit 1个英文字母是1个字节,也就是8位 4.一个汉字= ...

  6. nginx代理路径配置总结

    一.发现问题 配置nginx代理的时候,发现location配置的路径和代理的上下文路径的组合不同,服务端接收到的uri的路径不同,导致了controller的RequestMapping匹配出现问题 ...

  7. centos7启动httpd服务失败:Job for httpd.service failed because the control process exited with error code.

    centos7启动httpd命令有两个可以用 service httpd start    systemctl start httpd.service 如果出现如下报错 Job for httpd.s ...

  8. docker虚拟化平台构建

    docker虚拟化平台构建 从1.13版本以后的docker软件分为连个版本:企业版.社区版,在企业中推荐社区版本. 构建docker平台环境,系统选择centos7.x,推荐linux内核3.10 ...

  9. Flash 被禁止运行的方法

    下面以谷歌浏览器 和 火狐浏览器 来说明. █ 自2020 年以来, 谷歌浏览器(Chome)已全面禁止Flash的运行,我们可以通过如下方法开启: █ 火狐(FireFox) 也禁止,但需要点“运行 ...

  10. js 获取URL后面传的参数

    function GetRequest() { var url = location.search; //获取url中"?"符后的字串 var theRequest = new O ...