Bstar2016B的一些题的题解

T1 区间的价值

Description

我们定义“区间的价值”为一段区间的最大值*最小值。
一个区间左端点在L,右端点在R,那么该区间的长度为(R−L+1)。
现在聪明的杰西想要知道,对于长度为k的区间,最大价值的区间价值是多少。
当然,由于这个问题过于简单。
我们肯定得加强一下。
我们想要知道的是,对于长度为1∼n的区间,最大价值的区间价值分别是多少。

由于某种不可抗力,​​ 的值将会是1~10^9​​ 内随机产生的一个数。(除了样例)

Solution
没想到这题是这么水
关键在于加粗的那句话。
因为有了那句话,所以只要会暴力就能过==(当然不是裸的暴力)
我的做法是枚举一个最小值,然后暴力求向两边找到的一直满足该元素是最小值的位置。
然后判一下就好了。
期望是log 1.6 n
证明:
对于当前元素,如果它是最小的元素,那么要循环n次
若是次小,那么期望n/2次
若第三小,那么期望是n/3次
以此类推,第几小期望循环次数就是n/几。
这样的总期望是莫约log 1.6 n
当然ShinFeb大神是有更好的解法的,不想我这半吊子的期望,而且他是logn
当然他跑的比我慢==
unicornt的做法跟我差不多,但他的启发式好像更明显。所以他比我略快。。
比赛的时候竟然没A真是可惜。。
但总比unicornt看了一个小时还没A好==

[源代码]

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int M=1e5+5;
int n,A[M];ll ans[M],tmp[M];
inline void rd(int &a){
    a=0;char c;
    while(c=getchar(),!isdigit(c));
    do a=a*10+(c^48);
        while(c=getchar(),isdigit(c));
}
inline void Max(int &a,int b){if(a<b)a=b;}
inline void Max(ll &a,ll b){if(a<b)a=b;}
inline void gao(){
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=n;++i)rd(A[i]);
    for(int i=1;i<=n;++i){
        int mx=0,p1=i,p2=i;
        Max(ans[1],1ll*A[i]*A[i]);
        for(int j=i-1;j;--j){
            if(A[j]<A[i])break;
            Max(mx,A[j]);
            Max(tmp[i-j+1],1ll*A[i]*mx);
            p1=j;
        }
        mx=0;
        for(int j=i+1;j<=n;++j){
            if(A[j]<A[i])break;
            Max(mx,A[j]);
            Max(tmp[j-i+1],1ll*mx*A[i]);
            p2=j;
        }
        ll Mx=0;
        for(int i=1;i<=p2-p1+1;++i){
            Max(Mx,tmp[i]);
            Max(ans[i],Mx);
            tmp[i]=0;
        }
    }
    for(int i=1;i<=n;++i)
        printf("%I64d\n",ans[i]);
}
int main(){for(;cin>>n;)gao();}

T4 货物运输

Description
公元2222年,l国发生了一场战争。
小Y负责领导工人运输物资。
其中有m种物资的运输方案,每种运输方案形如li,ri。表示存在一种货物从li运到ri。
这里有n个城市,第i个城市与第i+1个城市相连(这里1号城市和n号城市并不相连),并且从i号城市走到i+1号或者从i+1号走到i号需要耗费1点时间。
由于高科技的存在,小Y想到了一种节省时间的好方案。在X号城市与Y号城市之间设立传送站,只要这么做,在X号城市走到Y号城市不需要耗费时间,同样的,从Y号城市走到X号城市也不需要耗费时间。
但是为了防止混乱,只能设立这么一条传送站。
现在这些运输方案同时进行,小Y想让最后到达目的地的运输方案时间最短。
在样例中,存在两条运输方案,分别是1号城市到3号与2号到4号,那么我们在2号城市与3号城市建立传送站,这样运输方案时间最长的只需要1点时间就可以了。

Solution
这是一道很好的数形结合。
首先我们可以想到二分(当然我一开始想到的是三分==)
对于二分出的答案,我们对于每一对l和r都可以得到满足他们的x和y的位置(这大概是一个菱形)
然后对于这么多个菱形求交。
我本来是想记录一个最右的左端点,以及一个最左的右端点,还有最下的上端点以及最上的下端点,然而这样并不对==
正解应该是解一个不等式
设二分的距离为p
可以列出方程|l-x|+|y-r|<=p
分零点讨论一下再取交集就可以==
[源代码]

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int M=1e6+5;
const int INF=1<<30;
int l[M],r[M],n,m;
inline void Min(int &x,int y){if(x>y)x=y;}
inline void Max(int &x,int y){if(x<y)x=y;}
inline bool check(int q){
    int mx1=-INF,mx2=-INF,mi1=INF,mi2=INF;
    for(int i=1;i<=m;++i){
        if(r[i]-l[i]<=q)continue;
        Max(mx1,l[i]+r[i]-q);
        Min(mi1,l[i]+r[i]+q);
        Max(mx2,l[i]-r[i]-q);
        Min(mi2,l[i]-r[i]+q);
    }
    return mx1<=mi1&&mx2<=mi2;
}
inline void rd(int &a){
    a=0;char c;
    while(c=getchar(),!isdigit(c));
    do a=a*10+(c^48);
        while(c=getchar(),isdigit(c));
}
inline void gao(){
    for(int i=1;i<=m;++i){
        rd(l[i]),rd(r[i]);
        if(r[i]<l[i])swap(r[i],l[i]);
    }
    int L=1,R=n,ans;
    while(L<=R){
        int mid=L+R>>1;
        if(check(mid))R=mid-1,ans=mid;
        else L=mid+1;
    }
    printf("%d\n",ans);
}
int main(){
    for(;~scanf("%d %d",&n,&m);)gao();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
set.seed(0) n = 50 p = 30 x = matrix(rnorm(n*p),nrow=n) bstar = c(runif(30,0.5,1)) mu = as.numeric(x%*%bstar) par(mar=c(4.5,4.5,0.5,0.5)) hist(bstar,breaks=30,col="gray",main="", xlab="True coefficients") library(MASS) set.seed(1) R = 100 nlam = 60 lam = seq(0,25,length=nlam) fit.ls = matrix(0,R,n) fit.rid = array(0,dim=c(R,nlam,n)) err.ls = numeric(R) err.rid = matrix(0,R,nlam) for (i in 1:R) { cat(c(i,", ")) y = mu + rnorm(n) ynew = mu + rnorm(n) a = lm(y~x+0) bls = coef(a) fit.ls[i,] = x%*%bls err.ls[i] = mean((ynew-fit.ls[i,])^2) aa = lm.ridge(y~x+0,lambda=lam) brid = coef(aa) fit.rid[i,,] = brid%*%t(x) err.rid[i,] = rowMeans(scale(fit.rid[i,,],center=ynew,scale=F)^2) } aveerr.ls = mean(err.ls) aveerr.rid = colMeans(err.rid) bias.ls = sum((colMeans(fit.ls)-mu)^2)/n var.ls = sum(apply(fit.ls,2,var))/n bias.rid = rowSums(scale(apply(fit.rid,2:3,mean),center=mu,scale=F)^2)/n var.rid = rowSums(apply(fit.rid,2:3,var))/n mse.ls = bias.ls + var.ls mse.rid = bias.rid + var.rid prederr.ls = mse.ls + 1 prederr.rid = mse.rid + 1 bias.ls var.ls p/n prederr.ls aveerr.ls cbind(prederr.rid,aveerr.rid) par(mar=c(4.5,4.5,0.5,0.5)) plot(lam,prederr.rid,type="l", xlab="Amount of shrinkage",ylab="Prediction error") abline(h=prederr.ls,lty=2) text(c(1,24),c(1.48,1.48),c("Low","High")) legend("topleft",lty=c(2,1), legend=c("Linear regression","Ridge regression")) par(mar=c(4.5,4.5,0.5,0.5)) plot(lam,mse.rid,type="l",ylim=c(0,max(mse.rid)), xlab=expression(paste(lambda)),ylab="") lines(lam,bias.rid,col="red") lines(lam,var.rid,col="blue") abline(h=mse.ls,lty=2) legend("bottomright",lty=c(2,1,1,1), legend=c("Linear MSE","Ridge MSE","Ridge Bias^2","Ridge Var"), col=c("black","black","red","blue")) 为每句代码加上注释解释
最新发布
05-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值