JZOJ 4611. 【NOI2016模拟7.11】接水问题 (贪心+A*+可持久化线段树)
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*+可持久化线段树)的更多相关文章
- [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)
题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...
- 【bzoj3524】【Poi2014】【Couriers】可持久化线段树(主席树)水题
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=62485671 向大(hei)佬(e)势力学(di ...
- 【模拟8.11】将军令(贪心&&树形DP)
只看45分的话,是树形DP....(当然也有能拿到70分+的大佬) 40分: 只考虑k==1的情况,树形DP 所以每个节点可能被父亲,自己,儿子控制 设f[MAXN][3],0表示儿子,1表示自己,2 ...
- 2019.02.11 bzoj1568: [JSOI2008]Blue Mary开公司(线段树)
传送门 题意简述:维护整体加一条线段,求单点极值. 思路: 直接上李超线段树维护即可. 代码: #include<bits/stdc++.h> #define ri register in ...
- 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) ...
- 2018.06.27 NOIP模拟 节目(支配树+可持久化线段树)
题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的 ...
- hdu 5475 模拟计算器乘除 (2015上海网赛H题 线段树)
给出有多少次操作 和MOD 初始值为1 操作1 y 表示乘上y操作2 y 表示除以第 y次操作乘的那个数 线段树的叶子结点i 表示 第i次操作乘的数 将1替换成y遇到操作2 就把第i个结点的值 替换成 ...
- [JZOJ6075]【GDOI2019模拟2019.3.20】桥【DP】【线段树】
Description N,M<=100000,S,T<=1e9 Solution 首先可以感受一下,我们把街道看成一行,那么只有给出的2n个点的纵坐标是有用的,于是我们可以将坐标离散化至 ...
- jzoj5986. 【WC2019模拟2019.1.4】立体几何题 (权值线段树)
传送门 题面 题解 不难看出每个点的大小为行列限制中较小的那一个(因为数据保证有解) 对于行的每个限制,能取到的个数是列里限制大于等于它的数的个数,同理,对于列是行里大于它的个数(这里没有等于,为了避 ...
随机推荐
- 基于ONOS的T-SDN Super控制器,突破多域网络运营的难关
在法国尼斯举办的IIR WDM波分论坛(Next Generation Optical Networking)上,华为展示了T-SDN(Transport SDN,传送SDN)领域的众多新技术,其中T ...
- 【Java8新特性】一张图带你领略Java8有哪些新特性
写在前面 很多小伙伴留言说,冰河你能不能写一些关于Java8的文章呢,看书看不下去,看视频进度太慢.好吧,看到不少读者对Java8还是比较陌生的,那我就写一些关于Java8的文章吧,希望对大家有所帮助 ...
- OSG程序设计之Hello World 2.0
现在为Hello World添加一些键盘响应事件. //需要多添加两个库:osgGAd.lib.osgd.lib 代码如下: #include <osgDB/ReadFile> #incl ...
- Lowest Common Ancestor of a Binary Search Tree(树中两个结点的最低公共祖先)
题目描述: Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in ...
- 面试被问了三次的http状态码到底有什么
面试被问了三次的http状态码到底有什么 想想很多人面试都会有被问到http的状态码的经历,我也是经历了三面,每次都有提及这个问题.今天就来细致的讨论一下HTTP的状态码,如有不足,欢迎留言交流: H ...
- pyhanlp安装教程
1.hanlp简介 HanLP是由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用.HanLP具备功能完善.性能高效.架构清晰.语料时新.可自定义的特点. Hanlp具有 ...
- Web的Cookies,Session,Application
Cookies:客户端(浏览器)存储信息的地方 Session:服务器的内置对象,可以在这里存储信息.按用户区分,每个客户端有一个特定的SessionID.存储时间按分钟计. Application: ...
- Arrays.binarySearch的返回值
如果查找的值包含在数组中,返回搜索的第一个值的下标: 如果查找的值不在数组中,返回(-插入点-1):插入点即为第一个大于此查找值的元素下标 插入点 为将该值插入数组的那一点:即第一个大于此键的元素下标 ...
- 设计模式之GOF23适配器模式
结构型模式 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的 类结构,用来解决更大的问题 适配器模式adapter 实际生活中的例子:转换器 适配器的两种方式: 1,类适配器(继承) /**需 ...
- 广义Fibonacci数列模n的循环节
见这里:http://blog.csdn.net/ACdreamers/article/details/25616461 有详细的分析推理 只找出了循环节的上限,设 f[n] = (af[n - 1] ...