2015 年 UOI 马上就要开始了,CSSYZ2015 信息队派出最强三位同
学组成“宇宙队”参加这次 ACM 比赛,周老师想让他们以最优的策
略去完成比赛,于是,将题目分为 5 等,编号 1 到 5,数字越大,难
度越大。
对于每一个同学,同一道题可能难度不一样,现在,周老师想知
道,如何安排学生做题顺序,能使难度值总和最低。
注意:每位同学只能做编号连续的题目,并且不能一道题不做输入:
第一行一个整数 N(3<=N<=150000),为题目数量
第二行到第四行,每行 N 个整数,代表每个题目对于三名同学的
难度
输入:
一行,最小难度总和
考虑暴力枚举两个断点,之后发现我们并不关心第二个断点的位置,只关心结果,so我们可以预处理第二个断点所可以产生的最优结果,然后暴力即可:
#include <cstdio> #include <iostream> using namespace std; #define GC getchar() #define R register #define ll long long #define MAXN 150000+5 #define inf 2147483647 inline void work1(); inline void work2(); template <typename T> inline void read(T &x); int n;int ans=2147483647; int a1[MAXN],a2[MAXN],a3[MAXN]; int s1[MAXN],s2[MAXN],s3[MAXN]; int main() { freopen("acm.in","r",stdin); freopen("acm.out","w",stdout); read(n); for(R int i=1;i<=n;i++) read(a1[i]),s1[i]=s1[i-1]+a1[i]; for(R int i=1;i<=n;i++) read(a2[i]),s2[i]=s2[i-1]+a2[i]; for(R int i=1;i<=n;i++) read(a3[i]),s3[i]=s3[i-1]+a3[i]; //for(R int i=1;i<=n;i++) cout<<s1[i]<<" ";cout<<endl; //for(R int i=1;i<=n;i++) cout<<s2[i]<<" ";cout<<endl; //for(R int i=1;i<=n;i++) cout<<s3[i]<<" ";cout<<endl; if(n>2000) work2(); else work1(); return 0; } template <typename T> inline void read(T &x) { x=0;char a=GC;int f=1; for(;a>'9'||a<'0';a=GC) if(a=='-') f=-1; for(;a>='0'&&a<='9';a=GC) x=(x<<1)+(x<<3)+(a^48); x*=f; } inline void work2() { R int pre=inf,maxnode=0; for(R int i=2;i<n;i++) if(s2[i]-s2[1]+s3[n]-s3[i]<pre) maxnode=i,pre=s2[i]-s2[1]+s3[n]-s3[i]; for(R int i=1;i<n;i++) { if(s1[i]-s1[0]+pre<ans) ans=s1[i]-s1[0]+pre; if(i<maxnode) pre-=a2[i+1]; else pre-=a3[i+1]; } pre=inf,maxnode=0; for(R int i=2;i<n;i++) if(s3[i]-s3[1]+s2[n]-s2[i]<pre) maxnode=i,pre=s3[i]-s3[1]+s2[n]-s2[i]; for(R int i=1;i<n;i++) { if(s1[i]-s1[0]+pre<ans) ans=s1[i]-s1[0]+pre; if(i<maxnode) pre-=a3[i+1]; else pre-=a2[i+1]; } pre=inf,maxnode=0; for(R int i=2;i<n;i++) if(s3[i]-s3[1]+s1[n]-s1[i]<pre) maxnode=i,pre=s3[i]-s3[1]+s1[n]-s1[i]; for(R int i=1;i<n;i++) { if(s2[i]-s2[0]+pre<ans) ans=s2[i]-s2[0]+pre; if(i<maxnode) pre-=a3[i+1]; else pre-=a1[i+1]; } pre=inf,maxnode=0; for(R int i=2;i<n;i++) if(s1[i]-s1[1]+s3[n]-s3[i]<pre) maxnode=i,pre=s1[i]-s1[1]+s3[n]-s3[i]; for(R int i=1;i<n;i++) { if(s2[i]-s2[0]+pre<ans) ans=s2[i]-s2[0]+pre; if(i<maxnode) pre-=a1[i+1]; else pre-=a3[i+1]; } pre=inf,maxnode=0; for(R int i=2;i<n;i++) if(s1[i]-s1[1]+s2[n]-s2[i]<pre) maxnode=i,pre=s1[i]-s1[1]+s2[n]-s2[i]; for(R int i=1;i<n;i++) { if(s3[i]-s3[0]+pre<ans) ans=s3[i]-s3[0]+pre; if(i<maxnode) pre-=a1[i+1]; else pre-=a2[i+1]; } pre=inf,maxnode=0; for(R int i=2;i<n;i++) if(s2[i]-s2[1]+s1[n]-s1[i]<pre) maxnode=i,pre=s2[i]-s2[1]+s1[n]-s1[i]; for(R int i=1;i<n;i++) { if(s3[i]-s3[0]+pre<ans) ans=s3[i]-s3[0]+pre; if(i<maxnode) pre-=a2[i+1]; else pre-=a1[i+1]; } printf("%d\n",ans); } inline void work1() { for(R int i=1;i<n;i++) for(R int j=i+1;j<n;j++) if(s1[i]-s1[0]+s2[j]-s2[i]+s3[n]-s3[j]<ans) ans=s1[i]-s1[0]+s2[j]-s2[i]+s3[n]-s3[j]; for(R int i=1;i<n;i++) for(R int j=i+1;j<n;j++) if(s1[i]-s1[0]+s3[j]-s3[i]+s2[n]-s2[j]<ans) ans=s1[i]-s1[0]+s3[j]-s3[i]+s2[n]-s2[j]; for(R int i=1;i<n;i++) for(R int j=i+1;j<n;j++) if(s2[i]-s2[0]+s1[j]-s1[i]+s3[n]-s3[j]<ans) ans=s2[i]-s2[0]+s1[j]-s1[i]+s3[n]-s3[j]; for(R int i=1;i<n;i++) for(R int j=i+1;j<n;j++) if(s2[i]-s2[0]+s3[j]-s3[i]+s1[n]-s1[j]<ans) ans=s2[i]-s2[0]+s3[j]-s3[i]+s1[n]-s1[j]; for(R int i=1;i<n;i++) for(R int j=i+1;j<n;j++) if(s3[i]-s3[0]+s1[j]-s1[i]+s2[n]-s2[j]<ans) ans=s3[i]-s3[0]+s1[j]-s1[i]+s2[n]-s2[j]; for(R int i=1;i<n;i++) for(R int j=i+1;j<n;j++) if(s3[i]-s3[0]+s2[j]-s2[i]+s1[n]-s1[j]<ans) ans=s3[i]-s3[0]+s2[j]-s2[i]+s1[n]-s1[j]; printf("%d\n",ans); }