离线赛 2019.10.31

2019.10.30

\[ Ameiyo \]



A

挺简单的一道 Dp 。。。看 这个博客


B

其实可以用 dijsktra 做这道题,但是每次用来更新的都是自己的次小值。

因为当你走到当前点时,老虎会让你不能走最小值,所以是用次小值更新。

每次也是拿次小值最小的点出来更新。

ll mi[N][2];

struct NODE {
    int id;
    ll w;
    inline int operator < (const NODE &__) const {
        return w > __.w;
    }
} ;

priority_queue < NODE > Q;

int main() {
    memset(mi, 0x3f, sizeof mi);

    n = read<int>(), m = read<int>(), q = read<int>();
    rep (i, 1, m) {
        int x = read<int>() + 1, y = read<int>() + 1, c = read<int>();
        Addedge(x, y, c), Addedge(y, x, c);
    }
    rep (i, 1, q) {
        int x = read<int>() + 1;
        mi[x][0] = mi[x][1] = 0, Q.push((NODE) { x, 0 });
    }

    while (!Q.empty()) {
        int u = Q.top().id; Q.pop();
        if (mk[u]) continue;
        mk[u] = true;
        for (int i = head[u], v; i; i = edge[i].nex) {
            v = edge[i].to;
            if (mk[v]) continue;
            ll tmp = mi[u][1] + edge[i].cost, flag = false;
            rep (d, 0, 1)
                (tmp < mi[v][d] && (swap(tmp, mi[v][d]), flag = true));
            if (flag) Q.push((NODE) { v, mi[v][1] });
        }
    }

    printf("%lld\n", mi[1][1]);
    return 0;
}

C

一道比较难想到的统计题。

有两种做法,但是两种做法都是基于暴力的 Dp (这个总要会吧。。),然后枚举所有询问跨越的点,通过对点两边的预处理然后合并。

  1. 分块,复杂度 $ O((n + q) * \sqrt {n * l}) $

其实我觉得这不能叫分块。。。

我们每 $ C $ 个点设置一个点,对于所有的点,我们处理出其左边一部分不选的情况下,左边每个点到他的 Dp 值,右边也一样。这样查询的时候就只用考虑中间有一块合并起来做贡献的情况。

因为 $ l $ 很小,所以每次直接暴力处理就行了。

const ll N = 100005, INF = 1e9;
const ll M = 55;
const int C = 4700;

#define max(a, b) ((a) > (b) ? (a) : (b))

int n, m, k, A[N], S[N], tmp[N], tot;
int fl[M][N], fr[M][N];

struct QUERY {
    int bl, l, r, id;
    inline int operator < (const QUERY &__) const {
        return bl < __.bl;
    }
}  Query[N];

int cur, Ans[N];

void Solve(int id) {
    memset(fl, 0, sizeof fl);
    memset(fr, 0, sizeof fr);
    rep (i, 0, k + 1) {
        dep (j, id - i - k + 1, 1)
            fl[i][j] = max(fl[i][j + 1],
                           fl[i][j + k] + S[j + k - 1] - S[j - 1]);
        rep (j, id + i + k - 1, n)
            fr[i][j] = max(fr[i][j - 1],
                           fr[i][j - k] + S[j] - S[j - k]);
    }
    for ( ; cur <= tot && Query[cur].bl == id; ++cur) {
        int l = Query[cur].l, r = Query[cur].r, ans = fl[1][l] + fr[0][r];
        rep (x, max(0, l + k - id - 1), min(k, r - id))
            ans = max(ans, fl[k - x][l] + fr[x + 1][r]
                            + S[id + x] - S[id + x - k]);
        Ans[Query[cur].id] = ans;
    }
}

int main() {
    n = read<int>(), k = read<int>();
    rep (i, 1, n) S[i] = S[i - 1] + (A[i] = read<int>());
    m = read<int>();
    rep (i, 1, m) {
        int l = read<int>(), r = read<int>();
        if (r - l + 1 <= C) {
            rep (i, k, r - l + 1)
                tmp[i] = max(tmp[i - 1],
                             tmp[i - k] + S[i + l - 1] - S[i + l - 1 - k]);
            Ans[i] = tmp[r - l + 1];
        } else Query[++tot] = (QUERY) { r / C * C, l, r, i };
    }

    sort(Query + 1, Query + tot + 1);

    cur = 1;
    rep (i, 1, n / C) Solve(i * C);

    rep (i, 1, m) printf("%d\n", Ans[i]);
    return 0;
}
  1. 分治,复杂度 $ O(n * \log n * k + q * k) $

每次选出来的点是当前区间的 $ mid $ ,其他同上。

const ll N = 100005, INF = 1e9;
const ll M = 55;

#define max(a, b) ((a) > (b) ? (a) : (b))

int n, m, k, A[N], S[N];

struct QUERY { int id, l, r; } ;
vector < QUERY > Que[N << 2];
int Ans[N];

#define ls (p << 1)
#define rs (p << 1 | 1)
void Push(int p, int l, int r, int L, int R, int id) {
    if (l == r) return (void) (Que[p].push_back((QUERY) { id, L, R }));
    int mid = (l + r) >> 1;
    if (R <= mid) Push(ls, l, mid, L, R, id);
    else if (L > mid) Push(rs, mid + 1, r, L, R, id);
    else Que[p].push_back((QUERY) { id, L, R });
}

int fl[M][N], fr[M][N];
void Solve(int p, int l, int r) {
    int mid = (l + r) >> 1, siz = Que[p].size();
    if (l != r) Solve(ls, l, mid), Solve(rs, mid + 1, r);
    if (!siz) return ;
    rep (i, 0, k) {
        rep (j, l, r) fl[i][j] = fr[i][j] = 0;
        dep (j, mid - i - k + 1, l)
            fl[i][j] = max(fl[i][j + 1],
                           fl[i][j + k] + S[j + k - 1] - S[j - 1]);
        rep (j, mid + i + k - 1, r)
            fr[i][j] = max(fr[i][j - 1],
                           fr[i][j - k] + S[j] - S[j - k]);
    }
    rep (i, 0, siz - 1) {
        int id = Que[p][i].id, l = Que[p][i].l, r = Que[p][i].r;
        int ans = fl[1][l] + fr[0][r];
        rep (x, max(0, l + k - mid - 1), min(k, r - mid))
            ans = max(ans, fl[k - x][l] + fr[x + 1][r]
                            + S[mid + x] - S[mid + x - k]);
        Ans[id] = ans;
    }
}

int main() {
    n = read<int>(), k = read<int>();
    rep (i, 1, n) S[i] = S[i - 1] + (A[i] = read<int>());
    m = read<int>();
    rep (i, 1, m) {
        int l = read<int>(), r = read<int>();
        Push(1, 1, n, l, r, i);
    }

    Solve(1, 1, n);

    rep (i, 1, m) printf("%d\n", Ans[i]);
    return 0;
}


\[ in \ 2019.10.31 \]

原文地址:https://www.cnblogs.com/Ameiyo/p/11771747.html

时间: 2024-11-04 06:11:31

离线赛 2019.10.31的相关文章

2019.10.31模拟赛

说在前面 考场遇见原题??? 上午刚做的 下午就\(T3\)考到了\(2333\) 然而还是因为忘了取模挂了28分 T1 Dove下跳棋 数据太水输出n-1可得90 Dove 喜爱下跳棋,在传统的跳棋基础之上,Dove 又延伸出了许多别的玩法.Dove 以一个一维数轴为棋盘下跳棋,总共会移动棋子?? ? 1 次.因为讨厌没有规律,所以Dove 每次只会恰好把棋子向右移动?? 个格子. Cicada 送给了Dove 一个长度为?? 的数列{??},为了表示感谢,Dove 打算以Cicada 送给他

2019.10.28~2019.10.31考试总结

连续几天的考试都没有总结,今天有些时间,总结一下这几场考试的情况. 10.28场 开场先读题,然后推了推T2,发现是水题.出于对期望的恐惧,没有选择研究T3,而是回头肝T1,想了很久,没有思路.打完T2,自己搓了一些数据,过了,回头打了T1的暴搜,再打了一个表,似乎部分分挺多的.再做T3,有点思路,但思路并不清晰,于是打了特殊数据就完了. 期望得分:70+100+20=190 最终得分:30+100+20=150 结果T1是DP,没看出来.唔...原题,地精部落,题果然还是做的太少了,有些人做过

lyc——2019.10.31

10:判决素数个数 总时间限制: 1000ms 内存限制: 65536kB 描述 输入两个整数X和Y,输出两者之间的素数个数(包括X和Y). 输入 两个整数X和Y(1 <= X,Y <= 105). 输出 输出一个整数,表示X,Y之间的素数个数(包括X和Y). 样例输入:1 100 样例输出:25 #include<cstdio> #include<algorithm> using namespace std; bool f[100005]; int main() {

从小工到专家 2019.10.31

第三章 基本工具 The Basic Tools       就像每个工匠刚刚开始职业生涯时,都会准备一套品质良好的基本工具,新程序员也需要准备一套的工具,也许它不是最好的,但最重要的是它在程序员看来是最顺手的. 随后学习与适应的过程开始,每种工具都有其自身的特性与古怪之处,都需要得到相应的特殊对待.随着时间的推移,工具与程序员的磨合程度越来越高,工具将程序员的才干放大,工具掌握的越好,程序员的效率越高.伴随一些特殊需求,程序员需要新的工具来解决问题.要像工匠一样,想着定期添加工具,总是寻找更好

2019.10.31 Zabbix环境初始化及添加监控主机

一.实验环境准备 Centos:192.168.200.111    server.zabbix.com Centos:192.168.200.112    agent.zabbix.com Windows10:192.168.200.110    windows10 111: hostname server.zabbix.com bash vim /etc/hostname中添加: server.zabbix.com vim /etc/hosts中添加: 192.168.200.111 ser

10.31 模拟赛

10.31 模拟赛 A LIS 考虑每个数字前从 $ m $ 降序构造到 $ a_i $ 即可. #include <iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> using namespace std; #define MAXN 300006 int n , m , k; int A[MAXN]; vector<int&g

使用RPM包离线安装MariaDB 10.0.20 , 基于CentOS 6.6-x86-64

使用RPM包[离线]安装 MariaDB 10.0.20,基于CentOS 6.6-x86-64 Minimal 湘中朱生 2015-07-01 于深圳福田 QQ: 872007255 MariaDB交流群: 198111730 文档说明: 1. 网上有很多关于MariaDB/Mysql数据库的安装技术博客文档,主要有源码编译安装和Yum源安装,有些写得很规范优秀,但很少有基于离线RPM包安装的. 2. 源码编译安装对于初学者而言门槛过高, 很容易打击MariaDB初学者学习探索的积极性; Yu

背水一战 Windows 10 (31) - 控件(按钮类): ButtonBase, Button, HyperlinkButton, RepeatButton, ToggleButton, AppBarButton, AppBarToggleButton

原文:背水一战 Windows 10 (31) - 控件(按钮类): ButtonBase, Button, HyperlinkButton, RepeatButton, ToggleButton, AppBarButton, AppBarToggleButton [源码下载] 作者:webabcd 介绍背水一战 Windows 10 之 控件(按钮类) ButtonBase Button HyperlinkButton RepeatButton ToggleButton AppBarButto

10.28 rsync工具介绍 - 10.29/10.30 rsync常用选项 - 10.31 rsync通过ssh同步

- 10.28 rsync工具介绍 - 10.29/10.30 rsync常用选项 - 10.31 rsync通过ssh同步 # 10.28 rsync工具介绍 -/A目录 --> /B目录(A目录更新了一个文件,每次更新都需要把A目录拷贝到B目录),如果用cp命令 比较浪费时间,耗费磁盘空间,磁盘压力 读写之类的, -使用rsync -av /etc/passwd /tmp/1.txt -a选项就是包含了好几个选项  ,v 是可视化,可以看到拷贝的过程 ``` [[email protecte