终于AK全场
JZOJ 4255 ACM
题目
在一开始,队伍的每一个人会评估每一道题的难度,难度会用1~5的整数表示,数字越大题目越难。然后他们会分配题目给每个人。题目会分成三个部分,每个队员会拿到一个非空的连续的题目代表了他要解决的问题。他们的策略是让难度评估系数最小。难度评估系数是三个队员对各自所拿到题目的难度评估的总和。你的任务是计算这个最小的难度评估系数。
分析
那么这道题数据有点水,于是我用了个贪心也能AC,不过这道题正解应该是动态规划,其实也很容易想,设 表示前 个题分到第 部分所得到胡最小难度评估系数,那么
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=150011;
int n,ans,a[N],b[N],c[N],dp1[N],dp2[N],dp3[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void answ(int *a,int *b,int *c){
memset(dp1,127/3,sizeof(dp1));
memset(dp2,127/3,sizeof(dp2));
memset(dp3,127/3,sizeof(dp3));
dp1[1]=a[1];
for (rr int i=2;i<=n;++i){
dp1[i]=dp1[i-1]+a[i];
dp2[i]=min(dp1[i-1],dp2[i-1])+b[i];
dp3[i]=min(dp2[i-1],dp3[i-1])+c[i];
}
ans=min(ans,dp3[n]);
}
signed main(){
freopen("acm.in","r",stdin);
freopen("acm.out","w",stdout);
n=iut(); ans=2147483647;
for (rr int i=1;i<=n;++i) a[i]=iut();
for (rr int i=1;i<=n;++i) b[i]=iut();
for (rr int i=1;i<=n;++i) c[i]=iut();
answ(a,b,c),answ(a,c,b),answ(b,a,c),answ(b,c,a),answ(c,a,b),answ(c,b,a);
return !printf("%d",ans);
}
JZOJ 4256 平均数
题目
给出包含一个 个整数的数组 。找出一段长度至少为 的连续序列,最大化它的平均值。
分析
那么这道题可以转换为二分它的平均值,判定是否非负,那么这样就比较简单了,不过数据还是有点水分,我自己做的程序被自己做的数据HACK掉了
代码
#include <cstdio>
#include <deque>
#include <cctype>
#define rr register
using namespace std;
int n,k,a[300001];
double now[300001];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
signed main(){
freopen("average.in","r",stdin);
freopen("average.out","w",stdout);
n=iut(); k=iut();
for (rr int i=1;i<=n;++i) a[i]=iut();
rr double l=1,r=1e6;
while (l+1e-8<r){
rr double mid=(l+r)/2,ans,minn=0;
for (rr int i=1;i<=n;++i) now[i]=now[i-1]+a[i]-mid; ans=now[k];
for (rr int i=1;i<=n-k;++i){
minn=min(minn,now[i]);
ans=max(ans,now[i+k]-minn);
}
if (ans>=0) l=mid; else r=mid;
}
return !printf("%.8lf",l);
}
JZOJ 4257 着色
题目
在一个图中用最多3种颜料(共有 种颜料)涂色,使相邻两个区域不同色
分析
首先
是一定不可能的
一共有8个图,24个测试点
第一个图:
首先在
种颜色选择3种,那么就是
,如果头可以选3种,那么其它地方只能选两种,也就是
,化简得到
,如果你是这么想的,恭喜你没分了,那么为什么会错呢,因为算重了在这三种只选了两种
的情况,那么应该为
第二个图:
那么这道题只能有三种颜色,所以不需要考虑是否算重,那么设大长方形的可选种类有
种,那么分别为
那么答案就是
第三个图:
那么显而易见答案就是
但是答案还是错了,和第一个图类似,必须去掉重复的答案
所以应该是
下同,所以不写了
代码
#include <cstdio>
#define rr register
using namespace std;
typedef long long ll;
ll q,m,ans;
signed main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
scanf("%lld%lld",&q,&m);
if (m==1) return !printf("0");
if (q==1){
if (m==2) ans=2;
else ans=m*(m-1)+m*(m-1)*(m-2)*((1<<18)-1);
}
else if (q==8){
if (m==2) ans=2;
else ans=m*(m-1)+m*(m-1)*(m-2)*((1<<29)-2)/3;
}
else if (q==5){
if (m==2) ans=0;
else ans=m*(m-1)*(m-2)<<1;
}
else if (q==2||q==7){
if (m==2) ans=0;
else ans=m*(m-1)*(m-2)<<4;
}
else if (q==3){
if (m==2) ans=2;
else ans=m*(m-1)+m*(m-1)*(m-2)*3;
}
else if (q==4){
if (m==2) ans=2;
else ans=m*(m-1)+m*(m-1)*(m-2)*((1<<12)-1);
}
else if (q==6){
if (m==2) ans=0;
else ans=m*(m-1)*(m-2);
}
return !printf("%lld",ans);
}