UESTC 764 失落的圣诞节 --RMQ/线段树

题意:n种物品,每种物品对不同的人都有不同的价值,有三个人选,第一个为普通学生,第二个是集,第三个是祈,集和祈可以选一样的,并且还会获得加分,集和祈选的普通学生都不能选,问三个人怎样选才能使总分最高。

解法: 先把集和祈选一样的和存到一个数组sum,然后可以枚举普通学生选的是哪个,再在sum的左边和右边找一个最大值,更新Maxi,然后再考虑集祈选的不同的情况,即在集的数组两边取个最大值,以及在祈的数组两边取个最大值,相加即可,如果集的最大值和祈的最大值为一个标记时,我们在前面的sum最大值就已经更新了Maxi,所以不加bonus肯定比sum中的小,所以直接找两个数组中的最大值就行了。

取区间的最大值可以用RMQ或者线段树。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 10017

int dsum[N][30],dji[N][30],dqi[N][30];
int sum[N],ji[N],qi[N],pu[N],LOG[N+7000];

void RMQ_init(int m)
{
    int i,j;
    for(i=1;i<=m;i++)
    {
        dsum[i][0] = sum[i];
        dji[i][0]  = ji[i];
        dqi[i][0]  = qi[i];
    }
    for(j=1;(1<<j)<=m;j++)
    {
        for(i=1;i+(1<<j)-1<=m;i++)
        {
            dsum[i][j] = max(dsum[i][j-1],dsum[i+(1<<(j-1))][j-1]);
            dji[i][j] = max(dji[i][j-1],dji[i+(1<<(j-1))][j-1]);
            dqi[i][j] = max(dqi[i][j-1],dqi[i+(1<<(j-1))][j-1]);
        }
    }
}
void getLog(int n)
{
    for(int i=0;i<=n;i++)
        LOG[i] = (int)(log((double)i)/log(2.0));
}
int RMQ(int (*d)[30],int l,int r)
{
    if(r < l) return 0;
    int k = LOG[r-l+1];
    return max(d[l][k],d[r-(1<<k)+1][k]);
}

int main()
{
    int t,i,j,n;
    scanf("%d",&t);
    getLog(15000);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++) scanf("%d",&pu[i]);
        for(i=1;i<=n;i++) scanf("%d",&ji[i]);
        for(i=1;i<=n;i++) scanf("%d",&qi[i]);
        for(i=1;i<=n;i++) scanf("%d",&sum[i]),sum[i] += ji[i]+qi[i];
        RMQ_init(n);
        int Maxi = 0;
        for(i=1;i<=n;i++)
        {
            int Normal = pu[i];
            int Sumleft = RMQ(dsum,1,i-1);
            int Sumright = RMQ(dsum,i+1,n);
            Maxi = max(Maxi,Normal+max(Sumleft,Sumright));
            int maxji = max(RMQ(dji,1,i-1),RMQ(dji,i+1,n));
            int maxqi = max(RMQ(dqi,1,i-1),RMQ(dqi,i+1,n));
            Maxi = max(Maxi,Normal+maxji+maxqi);
        }
        cout<<Maxi<<endl;
    }
    return 0;
}

时间: 2024-10-07 01:00:47

UESTC 764 失落的圣诞节 --RMQ/线段树的相关文章

POJ3264 Balanced Lineup RMQ 线段树

求区间内最大数和最小数的差,用两棵线段树,一个维护区间最大值,一个维护区间最小值. #include <stdio.h> #include <vector> #include <math.h> #include <string.h> #include <string> #include <iostream> #include <queue> #include <list> #include <algori

poj 3264 Balanced Lineup RMQ线段树实现

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 36613   Accepted: 17141 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

codeforces 487B B. Strip(rmq+线段树+二分)

题目链接: codeforces 487B 题目大意: 给出一个序列,要把序列划分成段,每一段最少有L个元素,段中的最大元素和最小元素之差不大于s,问划分的段的最少的数量是多少. 题目分析: 首先用rmq维护区间最大值和区间最小值. 然后按顺序扫描数组,线段树维护的数组,每个记录当前点作为最后一个点的前i个点划分的最小的段数,那么每次更新就是二分找到可以转移到我的最远距离,然后再选取与我距离大于l的那部分,取最小值即可. 最终结果就是线段树维护的数组的最后一个位置的元素的值. AC代码: #in

[RMQ] [线段树] POJ 3368 Frequent Values

一句话,多次查询区间的众数的次数 注意多组数据!!!! RMQ方法: 预处理 i 及其之前相同的数的个数 再倒着预处理出 i 到不是与 a[i] 相等的位置之前的一个位置, 查询时分成相同的一段和不同的一段 (RMQ) 但是要注意 to[i] 大于查询范围的情况, 以及RMQ时 x < y 的情况!! AC代码: #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib>

[luoguP1816] 忠诚(RMQ || 线段树)

传送门 其实我就是想练练 rmq 本以为学了线段树可以省点事不学 rmq 了 但是后缀数组中用 rmq 貌似很方便 所以还是学了吧,反正也不难 ——代码 1 #include <cstdio> 2 #define N 100001 3 #define min(x, y) ((x) < (y) ? (x) : (y)) 4 5 int n, m; 6 int a[N], d[N][21]; 7 8 int main() 9 { 10 int i, j, k, x, y; 11 scanf(

poj2763(lca / RMQ + 线段树)

题目链接: http://poj.org/problem?id=2763 题意: 第一行输入 n, q, s 分别为树的顶点个数, 询问/修改个数, 初始位置. 接下来 n - 1 行形如 x, y, w 的输入为点 x, y 之间连边且边权为 w. 接下来 q 行输入, 若输入形式为 1 x y 则为将点 x 的权值修改为 y , 若输入形式为 0 x 则询问 s 到 x 的最短距离为多少. 上一组的 x 为下一组的 s. 思路: 若去掉修改边权部分, 则为一个 lca 模板题. 对于修改边权

ACM学习历程—HDU5696 区间的价值(分治 &amp;&amp; RMQ &amp;&amp; 线段树 &amp;&amp; 动态规划)

http://acm.hdu.edu.cn/showproblem.php?pid=5696 这是这次百度之星初赛2B的第一题,但是由于正好打省赛,于是便错过了.加上2A的时候差了一题,当时有思路,但是代码就是过不去..这次应该是无缘复赛了.. 先不水了,省赛回来,我看了一下这个题,当时有个类似于快排的想法,今天试了一下,勉强AC了..跑了3S多. 思路就是我枚举区间左值lt,那么[lt, n]区间内最值的角标分别为mi和ma.于是设to = max(mi, ma).也就是说在to右侧的所有区间

UESTC 1073 秋实大哥与线段树(线段树---省时的建树)

题目链接:http://acm.uestc.edu.cn/#/problem/show/1073 “学习本无底,前进莫徬徨.” 秋实大哥对一旁玩手机的学弟说道. 秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构. 为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来作. 秋实大哥的题目要求你维护一个序列,支持两种操作:一种是修改某一个元素的值:一种是询问一段区间的和. Input 第一行包含一个整数n ,表示序列的长度. 接下来一行包含n  个整数a i  ,表示序列

POJ 3264 Balanced Lineup(RMQ/线段树)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 40312   Accepted: 18936 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh