【洛谷2019金秋营模拟赛1】

洛谷2019金秋营模拟赛1

T1 东方CannonBall

好吧这道题我应该只有暴力分 经hy大佬点拨我懂辽 然后我跑去交了代码==

30昏:枚举每个骰子点数,复杂度O(6^(x+y))
60昏: 分别枚举两个骰子的点数,计算出来每种点数和的方案数(除以6^n得到概率) 如果你扔出了\(i\)点,那你胜利的方案是对手扔出\([1,i)\),从小到大枚举你的点数,同时计算对手的前缀和。 6^10≈6e7,直接交可能过不了,注意到x*y比较小可以打表
100昏:
​ 同样计算每种点数的概率
​ 计算n个骰子的概率时,考虑最后一个骰子的点数为1-6的每种情况,可以从n-1个骰 子概率转移过来。
​ 记\(f[i][j]\)表示\(i\)个骰子扔出j的概率
\(f[i][j] = sum{f[i-1][j-k]/6}(1≤k≤6)\)
​ 递推即可,复杂度O(n²)

==并不是很想理解题解里的那个多项式的O(n logn)做法

int main(){
//  freopen("T1.txt","r",stdin);
    rd(n),rd(m),K=Max(n,m);
    for(int i=1;i<=6;++i) f[1][i]=1.0/6.0;
    for(int i=2;i<=K;++i)
        for(int j=i;j<=(i<<2)+(i<<1);++j)
            for(int k=1;k<=6;++k)
                if(j>k&&f[i-1][j-k]) f[i][j]+=f[i-1][j-k]/6.0;
    for(int i=n;i<=(n<<2)+(n<<1);++i)
        for(int j=Min(i-1,(m<<2)+(m<<1));j>=m;--j) ans+=f[n][i]*f[m][j];
    printf("%.2f",ans*100.0);putchar('%');
//  printf("M Used=%.3lf",(double)sizeof(f)/(1<<20));
    return 0; 
}

T2 しろは的军训列队

并没有看懂题解?

绝对值函数是分两段的一次函数
n个绝对值函数之和是n+1段分段一次函数,而这n个斜率变化的点就是aᵢ
按照aᵢ排序,最左边的那一段斜率是所有-bᵢ的和
往右扫,每经过一个点斜率变化+2bᵢ,这样可以得出每一段斜率
然后计算f(a₁),就可以按照斜率依次处理出每个点的函数值
最大值一定在分段处取值,求所有f(aᵢ)的最大值即可

看完 一个带权中位数模板? 一个位置有多个人就一直跳到下一个位置不同的人那里

考场丑代码

==其实我开始打是最暴力的那种暴力 很久没有搞过中位数了

暴力

struct node{int x,y;}a[N];
bool cmp1(node x,node y){return x.x
    
int main(){
//  freopen("T2.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i){
        rd(a[i].x);if(a[i].x!=a[i-1].x) xda=1;
    }
    sum=nw=0;
    for(int i=1;i<=n;++i) rd(a[i].y),sum+=a[i].y;
    sum>>=1;
//  if(!xda) return puts("0"),0;
    sort(a+1,a+n+1,cmp1);
    int pos;
    for(pos=1;pos<=n;++pos){
        nw+=a[pos].y;
        while(a[pos+1].x==a[pos].x&&pos<=n) nw+=a[++pos].y;
        if(nw>=sum) break;
    }
    ans=0ll;
    for(int i=1;i<=n;++i) ans+=1ll*abs(a[pos].x-a[i].x)*a[i].y;
    printf("%lld",ans);
    return 0; 
}

T3 勇者sky遇上的命中注定的恋人白羽竟然是妹妹2

看完 二昏!

然后就捯饬 每次二分都要分析好久那些边界啥的细节QAQ

然后打完三个样例都过了 美滋滋 觉得可能会超时也没管了==

结果65昏

65昏
struct node{int x,y;}a[N];
int mx,mn;
void query(int x,int y){
    int s=lg[y-x+1];
    mx=Max(Mx[x][s],Mx[y-(1<
     
      <
      
       lim) {++cnt,l=r;continue;}
        if(cnt==k+1) return 0;
    }
    return cnt<=k;
}
void work2(){
    double l=0,r=R,mid;
    while(l+eps
       
        =0.5) printf("%.1f\n",r);
    else printf("%d\n",(int)r);
}
int main(){
//  freopen("T3.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i].x),rd(a[i].y),R=Max(R,a[i].y);
    lg[0]=-1;
    for(int i=1;i<=n;++i) Mn[i][0]=Mx[i][0]=a[i].y,lg[i]=lg[i>>1]+1;
    Mn[n+1][0]=0,Mx[n+1][0]=inf;
    for(int j=1;j<=20;++j)
        for(int i=1;i+(1<
        
         <=n+1;++i)
        Mx[i][j]=Max(Mx[i][j-1],Mx[i+(1<<(j-1))][j-1]),
        Mn[i][j]=Min(Mn[i][j-1],Mn[i+(1<<(j-1))][j-1]);
    rd(m);
        for(int i=1;i<=m;++i) rd(k),work2();
    return 0; 
}   
        
       
      
     

首先撕烤只有一段的情况 极差的取值就是这一段的\((max+min)/2-mn\)

然后多段就可以二分 发现二分过程中会多次询问区间内的极大值和极小值 所以用ST表维护

然后还得优化== 每一段的长度不能像我一样一点一点增加枚举 每一段的长度也可二分!

题解中安利了另一种二分的方式 其实就是二进制拆分

从小到大枚举2ᵏ,如果当前解+2ᵏ仍然合法则加 上。本质是枚举答案的二进制位

struct node{int x,y;}a[N];
int mx,mn;
void query(int x,int y){
    int s=lg[y-x+1];
    mx=Max(Mx[x][s],Mx[y-(1<=0;--j)
            if(r+cm[j]<=n){
                query(l,r+cm[j]);
                if(((double)mx+mn)/2.0-mn*1.0<=lim) r+=cm[j];
            }
        l=r+1;
    }
    return l>n;
}
void work2(){
    double l=0,r=R,mid;
    while(l+eps=0.5) printf("%.1f\n",r);
    else printf("%d\n",(int)r);
}

int main(){
    freopen("T3.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i].x),rd(a[i].y),R=Max(R,a[i].y);
    cm[0]=1,lg[0]=-1;for(int i=1;i<=20;++i) cm[i]=cm[i-1]<<1;
    for(int i=1;i<=n;++i) Mn[i][0]=Mx[i][0]=a[i].y,lg[i]=lg[i>>1]+1;
    Mn[n+1][0]=0,Mx[n+1][0]=inf;
    for(int j=1;j<=20;++j)
        for(int i=1;i+cm[j]-1<=n+1;++i)
        Mx[i][j]=Max(Mx[i][j-1],Mx[i+cm[j-1]][j-1]),
        Mn[i][j]=Min(Mn[i][j-1],Mn[i+cm[j-1]][j-1]);
    rd(m);
    for(int i=1;i<=m;++i) rd(k),work2();
    return 0; 
}

你可能感兴趣的:(【洛谷2019金秋营模拟赛1】)