首页 > 代码库 > UESTC 764 失落的圣诞节 --RMQ/线段树
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 10017int 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;}
UESTC 764 失落的圣诞节 --RMQ/线段树
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。