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. github在版本库中删除某个文件的所有历史记录

    github的目的就是版本控制,记录每一个版本的变动.然而有的时候我们往往希望从版本库中彻底删除某个文件,不再显示在历史记录中.例如不小心上传了一堆错误的文件,或者不小心上传了帐号.密码,那么这个时候 ...

  2. Java中的==符号与equals()的使用(测试两个变量是否相等)

    Java 程序中测试两个变量是否相等有两种方式:一种是利用 == 运算符,另一种是利用equals()方法. 当使用 == 来判断两个变量是否相等时,如果两个变量是基本类型变量,且都是数值类型(不一定 ...

  3. 【Coursera-ML-Notes】线性回归(上)

    什么是机器学习 关于机器学习,有以下两种不同的定义. 机器学习是研究如何使电脑具备学习能力,而不用显式编程告诉它该怎么做. the field of study that gives computer ...

  4. 通过exp命令对Oracle数据库进行备份操作(提供两种情况的备份:备份本地,备份远程的数据库)

    exp 用户名/密码@数据库所在ip地址:数据库端口号/数据库的service-name file=存储到的位置 这个是能成功的 http://www.2cto.com/database/201402 ...

  5. Redux和React-Redux的实现(一):Redux的实现和context

    react使用redux做状态管理,实现多个组件之间的信息共享,解决了父子组件.兄弟组件之间的复杂通信问题.vue有vuex,总之是一种flux的思想.react提供了react-redux这个库,一 ...

  6. [BUAA软工]第零次博客作业---问题回答

    [BUAA软工]第0次博客作业 项目 内容 这个作业属于哪个课程 北航软工 这个作业的要求在哪里 第0次个人作业 我在这个课程的目标是 学习如何以团队的形式开发软件,提升个人软件开发能力 这个作业在哪 ...

  7. Mysql常用配置及优化

    [client]# 该目录下的内容常用来进行localhost登陆,一般不需要修改port = 3306 # 端口号socket = /var/lib/mysql/mysql.sock # 套接字文件 ...

  8. Hibernate笔记②--hibernate类生成表、id生成策略、级联设置、继承映射

    一.多表的一个关联关系 老师和学生是一对多的关系 student:tid属性 外键约束 对应teacher表中的id属性 teacher:id 在myeclipse的db窗口中选中两个表来生成类.   ...

  9. java List.get

    并不能 用如果List在i位置值不存在 并不能 List.get(i) !=null 判断 会抛异常 版权声明:本文为博主原创文章,未经博主允许不得转载.

  10. 我的JAVA运算符理解

    基本概念 原码,反码,补码 只需要记住这几句就够了  1.二进制的最高位是符号位:0表示正数,1表示负数 2.正数的原码,反码,补码都一样 3.负数的反码=它的原码符号位不变,其他位取反 4.负数的补 ...