首页 > 其他分享 >「JOISC 2020 Day4」治疗计划

「JOISC 2020 Day4」治疗计划

时间:2022-09-21 16:11:31浏览次数:79  
标签:include val int Day4 mid rd JOISC 2020 now

传送门


思路

淼淼题

考虑一个朴素的 DP:我们设 \(f_i\) 表示将 \([1,R_i]\) 的居民治好需要的最小代价

对于转移 \(f_i\longrightarrow f_j\),当且仅当 \(R_i-L_j+1\ge |T_j-T_i|\)

这是 \(O(n^2)\) 的;因为有取 \(\min\) 操作,我们考虑用最短路优化

观察式子,我们可以分两类讨论:

  1. 当 \(T_i\ge T_j\) 时,有 \(R_i-T_i+1\ge L_j-T_j\)

  2. 当 \(T_i < T_j\) 时,有 \(R_i+T_i+1\ge L_j+T_j\)

我们考虑建两棵线段树,每从一个点出发时,我们就在树上查询可以转移到的点

但这个复杂度似乎还是不对?

实际上,由于边权都是目标点的点权,结合 dijkstra 过程,当转移到目标点时,这个目标点一定就取到了最短路,因此每个点只会被转移一次

被转移后就在线段树上进行修改(改为 INF


#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define LL long long
#define FOR(i, x, y) for(int i = (x); i <= (y); i++)
#define ROF(i, x, y) for(int i = (x); i >= (y); i--)
#define PFOR(i, x) for(int i = he[x]; i; i = r[i].nxt)
inline int rd()
{
    int sign = 1, re = 0; char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
    while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
    return sign * re;
}
const int INF = 0x7fffffff;
int n, m, maxt;
struct Node
{
    int t, l, r, c;
}a[100005]; LL ans = 1e18;
#define pli std::pair<LL, int>
std::priority_queue<pli, std::vector<pli>, std::greater<pli>> q;
LL ndis; std::bitset<100005> vis;
namespace Seg
{
    #define ls (now << 1)
    #define rs  ((now << 1) | 1)
    int Mn1[400005], Mn2[400005];
    inline void up(int now) {Mn1[now] = std::min(Mn1[ls], Mn1[rs]), Mn2[now] = std::min(Mn2[ls], Mn2[rs]);}
    void build(int now, int l, int r)
    {
        if(l == r) return void((Mn1[now] = a[l].l - a[l].t, Mn2[now] = a[l].l + a[l].t));
        int mid = (l + r) >> 1;
        build(ls, l, mid), build(rs, mid + 1, r);
        up(now);
    }
    void queryL(int now, int l, int r, int to, int val)
    {
        if(Mn1[now] > val) return;
        if(l == r)
        {
            q.push(pli(ndis + a[l].c, l));
            Mn1[now] = Mn2[now] = INF;
            return;
        }
        int mid = (l + r) >> 1;
        queryL(ls, l, mid, to, val);
        if(mid < to) queryL(rs, mid + 1, r, to, val);
        up(now);
    }
    void queryR(int now, int l, int r, int to, int val)
    {
        if(Mn2[now] > val) return;
        if(l == r)
        {
            q.push(pli(ndis + a[l].c, l));
            Mn1[now] = Mn2[now] = INF;
            return;
        }
        int mid = (l + r) >> 1;
        if(to <= mid) queryR(ls, l, mid, to, val);
        queryR(rs, mid + 1, r, to, val);
        up(now);
    }
}
inline void dij()
{
    FOR(i, 1, m) if(a[i].l == 1)
        q.push(pli(a[i].c, i));
    while(!q.empty())
    {
        while(!q.empty() && vis[q.top().second]) q.pop();
        if(q.empty()) break;
        int now = q.top().second; ndis = q.top().first;
        vis[now] = 1; q.pop();
        if(a[now].r == n) ans = std::min(ans, ndis);
        if(now > 1) Seg::queryL(1, 1, m, now - 1, a[now].r - a[now].t + 1);
        if(now < m) Seg::queryR(1, 1, m, now + 1, a[now].r + a[now].t + 1);
    }
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    n = rd(), m = rd();
    FOR(i, 1, m) a[i] = (Node){rd(), rd(), rd(), rd()};
    std::sort(a + 1, a + 1 + m, [&](Node a, Node b){return a.t < b.t;});
    Seg::build(1, 1, m);
    dij();
    ans == 1e18 ? puts("-1") : printf("%lld", ans);
    return 0;
}

标签:include,val,int,Day4,mid,rd,JOISC,2020,now
From: https://www.cnblogs.com/zuytong/p/16715943.html

相关文章

  • P7076 [CSP-S2020] 动物园
    [CSP-S2020]动物园题目描述动物园里饲养了很多动物,饲养员小A会根据饲养动物的情况,按照《饲养指南》购买不同种类的饲料,并将购买清单发给采购员小B。具体而言,动物世......
  • 【解题报告】[JOISC 2014] 挂饰
    【我也不知道什么TM的系列】JOISC2014挂饰经典的传送门写这篇文章来告诉大家写贪心的重要性心路历程看到这道题第一印象:woc蓝题看了一下样例:woc水题贪了60分:woc......
  • 关于IntelliJ IDEA 2020.1 勾选delegate IDE build/run actions to maven后测试类方法
    今天写MAVEN项目时,在执行测试类时发现方法都执行了两次,比如我执行insertAccout的测试类,就保存了两条相同的记录,执行别的测试类的时候,都会附带执行一次插入,产生一条记录,看了......
  • 20201302姬正坤第十章学习笔记
    第三周学习笔记第十章第十章的主要内容是研究sh编程。对于sh编程的介绍分为以下几个方面:sh脚本与C程序sh脚本的编写sh控制语句sh汉书知识点归纳:经过一整章的......
  • 20201306吴龙灿第十章学习笔记
    知识点归纳这一章的主要内容包含了sh编程的绝大部分内容。但是在此之前,还是要强调一下诸如Python、C、Java这些程序语言的特点。1.Python(一)Python是什么?Python是一......
  • 20201322陈俊池学习笔记3
    第十章sh编程一、知识点归纳10.1sh脚本sh脚本是一个包含sh语句的文本文件,命令解释程序sh要执行该语句。创建mysh: #!/bin/bash #commentline echohello使......
  • day40-网络编程02
    Java网络编程024.TCP网络通信编程基本介绍基于客户端--服务端的网络通信底层使用的是TCP/IP协议应用场景举例:客户端发送数据,服务端接收并显示控制台基于Scoket的TC......
  • 2022-2023-1 20201324《信息安全系统设计与实现(上)》第10章
    目录0程序设计语言与shell脚本(1)一门程序设计语言有哪些必备的要素和技能(2)这些要素和技能在shell脚本中是如果呈现出来的1sh脚本2sh脚本与C程序3命令行参数4sh变量5sh......
  • 20201206韩进学习笔记3
    sh编程sh脚本包含sh语句的文本文件,命令解释程序sh要执行该语句。sh脚本与C程序sh:解释程序,逐行读取sh脚本文件并直接执行,若行是可执行命令且为内置命令,则可直接执行。......
  • 20201318李兴昕第十章学习笔记
    第十章:sh编程知识点归纳总结:本章讨论了sh编程,阐释了sh脚本和不同版本的sh。比较了sh脚本与C程序,并指出了解释语言和编译语言的区别;说明了如何编写sh脚本,包括sh变量,sh语句......