UESTC 764 失落的圣诞节 直接or线段树orRMQ

来源:互联网 发布:中美双边贸易数据 编辑:程序博客网 时间:2024/04/27 17:44

失落的圣诞节

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
 

在樱满集(Ouma Shuu, 简称集)成功阻止修一郎博士,救出楪祈(Yuzuriha Inori, 简称祈)之后,由于默示录病毒的爆发,天王州环状七号线内被封锁,

集所在的学校也在此之内。封锁很快变成了清扫,为了打败政府的幽灵部队,逃出封锁区域,集在学校建立了void王国。

每个学生都有自己专属的void,每种专属void都有对应的属性值,集能将各个学生专属的void取出来,并交给他们使用。普通学生不能使用别人

void,但是作为主角的集和祈能使用任意学生的void,显然,如果集或者祈使用了某种void,那么该void的主人就不能再使用了。当void

集或者祈手中,void的属性值会有所改变,并且集和祈能同时使用同一个学生的void,且使用相同void的时候,还会有额外加成的属性值(这就

是传说中爱的力量?)

为了打倒幽灵部队,集决定派出3个人,他自己,祈和一个普通学生(精英战术!)。现在希望你帮助集求出,他们3个人使用的void的属性值的

和能达到的最大值。

Input

首先输入一个t,表示输入数据组数,对于每组数据。

第一行为一个整数n,表示拥有void的人数。(3n10000,所有属性值小于2000

第二行为n个正整数,每个整数表示该种void的主人用它时的属性值。

第三行为n个正整数,每个整数表示该种void被集使用时的属性值。

第四行为n个正整数,每个整数表示该种void被祈使用时的属性值。

第五行为n个正整数,每个整数表示该种void被集和祈同时使用时的属性加成值。

Output

每组数据输出一行。输出满足题目要求的最大属性值。

Sample input and output

Sample InputSample Output
14200 300 400 200150 200 450 400100 300 700 500100 100 100 100
1550

Hint

在正常情况下,同一种void不能被多个人使用,唯一的特例情况是题面中所说的集和祈同时使用的时候。

样例解释:

  1. 普通学生使用第二种void,属性值为300
  2. 集使用第三种void,属性值为450
  3. 祈使用第三种void,属性值为700

属性加成为100

My Solution

首先是有组合void的,分成2类 
1、maxN + maxSQ ; 
2、1)maxN2 + maxSQ ;2)maxN + maxSQ2

然后没有组合void的,分成3类
1、maxN +  这个时候对应位置为mni 
然后在它的两边分别扫描S、Q 可以得 max4
2、maxN2 + 这个时候对应位置为mni2 
然后在它的两边分别扫描S、Q 可以得 max5
3、maxN3 + 这个时候对应位置为mni3 
然后在它的两边分别扫描S、Q 可以得 max6      //因为可能N的第1大和第2大位置都被占了,且集和祈的效果更好

具体请看下面,虽然Length挺长的,但Time还是做过那个题目目前为止最快的,Memory也尽可能小了,别人懒得优化这个题目吧

#include <cstdio>#include <algorithm>//#define LOCALusing namespace std;const int maxn=10000+8;int N[maxn],S[maxn],Q[maxn],Sha,sum[maxn];int main(){    #ifdef LOCAL    freopen("a.txt","r",stdin);    #endif // LOCAK    int T,n,maxN,mni,mni2,maxN3,mni3, maxSQ,mqsi, maxs, maxq;    scanf("%d",&T);    while(T--){        maxN=0;maxSQ=0;        scanf("%d",&n);        for(int i=0;i<n;i++)            {scanf("%d",&N[i]);if(maxN<N[i]) {maxN=N[i];mni=i;}  }        for(int i=0;i<n;i++)            scanf("%d",&S[i]);        for(int i=0;i<n;i++)            scanf("%d",&Q[i]);        for(int i=0;i<n;i++)          {scanf("%d",&Sha);sum[i]=Sha+S[i]+Q[i];if(maxSQ<sum[i]) {maxSQ=sum[i];mqsi=i;}   }        int max1=0,max2=0,max3=0, maxSQ2=0,maxN2=0;        if(mni!=mqsi) max3=maxSQ+maxN;        else{            for(int i=0;i<n;i++)                if(i!=mqsi) maxSQ2=max(maxSQ2,sum[i]);            max1=maxN+maxSQ2;               //max0            for(int i=0;i<n;i++)                if(i!=mni) if(maxN2<N[i]) {maxN2=N[i];mni2=i;}            max2=maxN2+maxSQ;            max3=max(max1,max2);        }        int max4=0,max5=0,max6=0;        maxs=0;maxq=0;        for(int i=0;i<mni;i++){            maxq=max(maxq,Q[i]);            maxs=max(maxs,S[i]);        }        for(int i=mni+1;i<n;i++){            maxq=max(maxq,Q[i]);            maxs=max(maxs,S[i]);        }        max4=maxq+maxs+maxN;        maxq=0;maxs=0;        for(int i=0;i<mni2;i++){            maxq=max(maxq,Q[i]);            maxs=max(maxs,S[i]);        }        for(int i=mni2+1;i<n;i++){            maxq=max(maxq,Q[i]);            maxs=max(maxs,S[i]);        }        max5=maxq+maxs+maxN2;        maxN3=0;        for(int i=0;i<n;i++)            if(i!=mni&&i!=mni2) if(maxN3<N[i]) {maxN3=N[i];mni3=i;}        maxq=0;maxs=0;        for(int i=0;i<mni3;i++){            maxq=max(maxq,Q[i]);            maxs=max(maxs,S[i]);        }        for(int i=mni3+1;i<n;i++){            maxq=max(maxq,Q[i]);            maxs=max(maxs,S[i]);        }        max6=maxq+maxs+maxN3;        printf("%d",max(max3,max(max4,max(max5,max6))));        if(T) printf("\n");    }    return 0;}

没有用线段树,这里有3个要扫描的数组,再用数组建树,加上函数相对for(;;)的时间开销,时间复杂度差不多了,可能还会慢一点。
并且用for可以轻松的S、Q一起扫,
所以在这里就直接搞了。

谢谢

0 0