Portal --> who knows ==

Description

  数轴上面有一些洞,有一些老鼠,每个洞有一个容量限制,一只位于\(x\)的老鼠进到位于\(y\)的洞要花费\(|x-y|\)的代价,问所有老鼠都进洞的最小代价,如果没有合法方案输出\(-1\)

  数据范围:\(n,m<=10^6,1<=c_i<=n\),其中\(c_i\)表示每个洞的容量,\(0<=\)位置\(<=10^9\)

  

Solution

  这题的话。。长得像一个dp。。但是如果直接莽显然是不行的。。

​  注意到一个点:将洞和老鼠都按照位置排序,最优方案中进入同一个洞的老鼠一定是一段连续的区间,那么记\(f[i][j]\)表示前\(i\)个洞,前\(j\)只老鼠已经进洞了的最小代价,转移的话:

\[f[i][j]=min(f[i-1][k]+sum[j]-sum[k])
\]

  其中\(k\)的枚举范围是\([j-c[i],j]\),\(sum[j]\)表示的是\(\sum\limits_{p=1}^j|rat_p-hole_i|\)

​  那么线段树优化一下就有一个\(O(nmlogn)\)的做法(然而实际上好像直接单调栈什么的搞一搞除去排序就是\(O(nm)\)了)

​   

  然后注意到这个dp是没有前途的。。(没有办法继续优化了),所以换一种思路

  不选择分开考虑,而是选择将所有的老鼠和洞放在一起,这里有一种很妙的用堆的做法(疯狂orzhwc),用两个堆分别维护老鼠和洞

  我们将老鼠和洞放在一条线上,一只老鼠要么会被丢到前面,要么会被丢到后面,那么我们从左往右扫,考虑如果扫到一只老鼠,我们先无脑将它丢到它前面的离它最近的有容量的洞里面,更优情况的替换我们放在扫到一个洞的时候处理

  扫到一个洞的时候,如果说有只当前被丢到前面洞里的老鼠丢到这个洞里面会比当前更优,那么就把这只老鼠丢进来,更新当前答案,具体的判断方式是:我们将前面的那个洞的位置以当前老鼠为对称轴对称过来,如果说对称过来得到的位置比当前洞的位置更大,那么说明当前洞更优

  具体处理的话就是用一个堆维护被丢进前面的洞里的老鼠对应的洞的对称值(也就是\(rat+hole\),其中\(rat\)表示这只老鼠的位置,\(hole\)表示对应洞的位置),然后如果堆顶的那个老鼠不能被当前这个洞更新,那肯定也不能被后面的洞更新了,所以直接弹掉

  然而这里有一个问题,当前的决策放在后面不一定是最优的,也就是说有的老鼠当前可能丢到后面比较优,但是放在全局可能就是丢到前面比较优了,为了应对这种情况,我们需要一个撤销操作,具体的实现就是,如果说在扫到一个洞的时候,我们用这个洞更新了某只老鼠,那么对应的我们要多加一个相当于撤销操作的洞到洞的堆里面,撤销的具体含义就是:如果说当前的老鼠选了一个撤销洞,那么就相当于令被撤销洞更新的老鼠重新回到更新前的洞里,并且将当前的老鼠丢到这个洞里

​  实现上的话,假设撤销洞位置为\(y\),被撤销洞更新的老鼠\(A\)在更新前在的洞是\(x\),\(delta\)是该老鼠选\(y\)比选\(x\)优多少,那么撤销洞的位置就应该为\(y+delta\),并且容量为\(1\),之所以这么设是因为:如果说当前的老鼠\(B\)选了这个洞,那么\(ans\)会被加上\(rat_B-(y+delta)\),也就是相当于将\(delta\)去掉(老鼠\(A\)回到\(x\)),然后再加上老鼠\(B\)选\(y\)这个洞的贡献

  然后一路扫过去就好了ovo

  

  mark:撤销洞的思路很有意思,mark一下

  

  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
#define Pr pair<ll,int>
#define mp make_pair
using namespace std;
const int N=1000010;
const ll inf=1LL<<60;
struct Data{
int p,c,ty;
friend bool operator < (Data x,Data y){
return x.p==y.p?x.ty<y.ty:x.p<y.p;
}
}a[N*2];
priority_queue<Pr> hole;
priority_queue<ll> rat;
int n,m,cnt;
ll ans;
void solve_rat(int i){
ll w=inf;
Pr tmp;
if (!hole.empty()){
tmp=hole.top(); hole.pop();
w=a[i].p-tmp.first;
--tmp.second;
if (tmp.second)
hole.push(tmp);
}
rat.push(w+a[i].p);
ans+=w;
}
void solve_hole(int i){
ll delta;
while (a[i].c&&!rat.empty()&&a[i].p<rat.top()){
delta=a[i].p-rat.top(); rat.pop();
ans+=delta;
--a[i].c;
hole.push(mp(a[i].p+delta,1));
}
if (a[i].c)
hole.push(mp(a[i].p,a[i].c));
}
void solve(){
for (int i=1;i<=cnt;++i)
if (a[i].ty==0)
solve_rat(i);
else
solve_hole(i);
printf("%lld\n",ans);
}
void print(Pr x){printf("(%d,%d)\n",x.first,x.second);} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y;
ll sum=0;
scanf("%d%d",&n,&m);
cnt=0;
for (int i=1;i<=n;++i) scanf("%d",&a[++cnt].p),a[cnt].ty=0;
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
if (!y) continue;
a[++cnt].p=x; a[cnt].c=y; a[cnt].ty=1;
sum+=y;
}
if (sum<n){printf("-1\n"); return 0;}
sort(a+1,a+1+cnt);
solve();
}

【noip模拟】D(==)的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #52 - Thinking Bear #1 (NOIP模拟赛)

    A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...

  10. CH Round #49 - Streaming #4 (NOIP模拟赛Day2)

    A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...

随机推荐

  1. 如何掌握 Kubernetes ?系统学习 k8s 的大纲一份

    深度剖析 Kubernetes 深度剖析 k8s 如何学习 Kubernetes ?如何入门 Kubernetes? 为了帮帮初学者,2018 年 InfoQ 旗下(就是你知道的那个 InfoQ 哇) ...

  2. RabbitMQ理论部分

    概念 queue        队列 exchange   交换机 bind          绑定 channel     通道 一个发送消息流程包含上述四个概念.消息经过channel传递给exc ...

  3. jenkins展示report测试报告的配置

    HTML报告展示 1. 需要HTML Publisher plugin插件 2. 在workspace下的工程(构建)中的目录中存储测试报告 在Jenkins中新建一个job,进入配置项. 首先通过p ...

  4. yarn (npm) 切换设置镜像源

    设置镜像源 1.查看一下当前源 yarn config get registry 2.切换为淘宝源 yarn config set registry https://registry.npm.taob ...

  5. JAVA开发环境的熟悉

    北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序设计 班级:1352 姓名:马悦 学号:20135235 成绩: 指导教师:娄嘉鹏 实验日期:2015.4.13 实验密级: 预习程度 ...

  6. Task 6.2站立会议一

    今天大家把这两天查的资料都拿出来整合到了一起,并仔细分析了其中的联系和区别. 因为大家每个人的思路都不一样,有各种各样的想法和不同的意见,所以最终统一意见是很难的一个过程.开始大家认我们可以做一个单独 ...

  7. 复杂PC问题——信号量与共享存储区

    #include <stdio.h> #include <unistd.h> #include <sys/ipc.h> #include <sys/sem.h ...

  8. HDU 1565 方格取数(1) 轮廓线dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...

  9. gdb调试器学习链接

    首先要带 -g 选项用gcc编译 常用指令:http://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/gdb.html#gdb 带main的命令行参 ...

  10. css布局 弹性布局 和 网格布局

    这里就不写这两种布局的内容了 弹性布局链接:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html 网格布局链接:https://www.ji ...