51nod1624 取余最长路 前缀和 + set

由于只有3行,因此只会会换行2次,假设$x, y$分别为这两次的换行点

那么答案为$S[1][x] +S[2][y] - S[2][x - 1] + S[3][n] - S[3][y - 1]$

其中,$S[i]$表示第$i$行的前缀和

令$a[x] = S[1][x] - S[2][x - 1], b[y] = S[2][y] - S[3][y - 1]$

考虑枚举$x$,那么问题转化为询问在一堆数中求一个数$k$使得$v (= a[x] + S[3][n]) + k \;mod\;p$最大

分两种情况考虑,第一种$v + k \in [v, mod - 1]$,那么$k \in [0, mod - k - 1]$,并且$k$越大越好

第二种不如第一种好,但有可能不得不选,$v + k \in [1, v - 1]$,同样时$k$越大越好

也就是说,需要一种支持插入,查询前驱和最大值的数据结构,$set$就可以

注:倒叙枚举$x$,可以做到不删除

复杂度$O(n \log n)$

#include <set>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

extern inline char gc() {
    static char RR[23456], *S = RR + 23333, *T = RR + 23333;
    if(S == T) fread(RR, 1, 23333, stdin), S = RR;
    return *S ++;
}
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > ‘9‘ || c < ‘0‘) { if(c == ‘-‘) w = -1; c = gc(); }
    while(c >= ‘0‘ && c <= ‘9‘) p = p * 10 + c - ‘0‘, c = gc();
    return p * w;
}

#define ll long long
#define ri register int
#define sid 200050

int n, ans, mod;
int s[4][sid], a[sid], b[sid];

set <int> ex;

int main() {
    n = read(); mod = read();
    for(ri i = 1; i <= 3; i ++)
    for(ri j = 1; j <= n; j ++)
    s[i][j] = (s[i][j - 1] + read()) % mod;

    for(ri i = 1; i <= n; i ++) a[i] = (s[1][i] - s[2][i - 1] + mod) % mod;
    for(ri i = 1; i <= n; i ++) b[i] = (s[2][i] - s[3][i - 1] + mod) % mod;

    int der = s[3][n]; ex.insert(1);
    for(ri i = n; i >= 1; i --) {
        ex.insert(-b[i]);
        int v = (der + a[i]) % mod;
        int p = *ex.lower_bound(-(mod - 1 - v));;
        if(p == 1) ans = max(ans, (v - *(++ ex.begin())) % mod);
        else ans = max(ans, v + -p);
    }

    printf("%d\n", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/reverymoon/p/9556662.html

时间: 2024-10-05 19:53:00

51nod1624 取余最长路 前缀和 + set的相关文章

1624 取余最长路 (前缀和+set二分)

1624 取余最长路 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱乐值为所经过的位置的权的总和. 有一天,她被下了恶毒的诅咒,这个诅咒的作用是将她的娱乐值变为对p取模后的值,这让佳佳十分的不开心,因为她无法找到一条能使她得到最大娱乐值的路径了! 她发现这个问题实在是太困难了,既然这样,那就只在3*n的矩阵内进行游戏吧! 现在的问题是,在一个3*n的带权矩阵中,从(1,1)走到(3,n),只能往右往下移动,问在模p意义下的移动过程中的权总和最大是多

1624 取余最长路(set)

1624 取余最长路 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 佳佳有一个n*m的带权矩阵,她想从(1,1)出发走到(n,m)且只能往右往下移动,她能得到的娱乐值为所经过的位置的权的总和. 有一天,她被下了恶毒的诅咒,这个诅咒的作用是将她的娱乐值变为对p取模后的值,这让佳佳十分的不开心,因为她无法找到一条能使她得到最大娱乐值的路径了! 她发现这个问题实在是太困难了,既然这样,那就只在3*n的矩阵内进行游戏吧! 现在的问题是,在一个3*n的带权矩阵中,从(

51 nod 1624 取余最长路 思路:前缀和 + STL(set)二分查找

题目: 写这题花了我一上午时间. 下面是本人(zhangjiuding)的思考过程: 首先想到的是三行,每一行一定要走到. 大概是这样一张图 每一行长度最少为1.即第一行(i -1) >= 1,第二行 (j - i) >= 1,第三行 (n - j) >= 1. 我们要求的就是这条路径上的和. 我们发现只要 i 和 j 固定了,结果就固定了. 如果每次都要重新求和的话时间复杂度肯定不够,所以我这个时候想到了前缀和. 用sum[a][b]表示第a行(总共只有3行)前b个数字的和. 第一行可

简单Dp----最长公共子序列,DAG最长路,简单区间DP等

/* uva 111 * 题意: * 顺序有变化的最长公共子序列: * 模板: */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[100]; int mu[100]; int Dp[100][100]; int main() { int n,x; scanf("%d", &n

【分治】取余运算

问题 E: [分治]取余运算 时间限制: 1 Sec  内存限制: 128 MB提交: 16  解决: 6[提交][状态][讨论版] 题目描述 输入b,p,k的值,求bp mod k的值.其中b,p,k*k为长整型数. 输入 三个整数,分别为b,p,k的值 输出 bp mod k 样例输入 2 10 9 样例输出 2^10 mod 9=7 提示 解题思路:分治,顾名思义,把一个大问题分解为多个小问题. 这里有一个公式,利用这个公式通过递归求得. 代码: #include <iostream>

poj 3349:Snowflake Snow Snowflakes(哈希查找,求和取余法+拉链法)

Snowflake Snow Snowflakes Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 30529   Accepted: 8033 Description You may have heard that no two snowflakes are alike. Your task is to write a program to determine whether this is really true. Y

Luogu P1226 取余运算||快速幂(数论,分治)

P1226 取余运算||快速幂 题目描述 输入b,p,k的值,求b^p mod k的值.其中b,p,k*k为长整型数. 输入输出格式 输入格式: 三个整数b,p,k. 输出格式: 输出"b^p mod k=s" s为运算结果 输入输出样例 输入样例#1: 2 10 9 输出样例#1: 2^10 mod 9=7 这是一道很有趣的水题,如果知道公式. 一般求解会溢出,导致答案错误. 这里介绍取模的一个公式: a*b%k=(a%k)*(b%k)%k. 在我们这道题中是b^p = (b^(p/

hdu 1226 超级密码 bfs+取余判重

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2808    Accepted Submission(s): 897 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的

codevs 1497取余运算

1497 取余运算 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamon 题目描述 Description 输入b,p,k的值,编程计算bp mod k的值.其中的b,p,k*k为长整型数(2^31范围内). 输入描述 Input Description b p k 输出描述 Output Description 输出b^p mod k=? =左右没有空格 样例输入 Sample Input 2  10  9 样例输出 Sample Output 2^10 mod