• 【模拟8.07】柱形图(三分)


    考试时没审清题,内存超限.......

    事实上这是个三分题,

    因为我们先假设一个最高点和最高点的高度,随着最高点高度的增加,

    其他点的贡献为abs(a[j]-(h[i]-abs(i-j)))(j为最高点)

    所以点的贡献的和是一个单峰函数(下凹的)

    那么我们三分即可

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<string>
     7 #include<map>
     8 #include<vector>
     9 #include<queue>
    10 #include<set>
    11 #define MAXN 200010
    12 #define ps push_back
    13 #define int long long
    14 using namespace std;
    15 int n;int a[MAXN];int max_r=0;int l,r;int minn=0x7ffffffffffff;
    16 int work(int x,int root)
    17 {
    18     int sum=0;
    19     for(int i=1;i<=n;++i)
    20     {
    21         int me=x-abs(i-root);
    22         sum+=abs(a[i]-me);
    23     }
    24     minn=min(minn,sum);    
    25     return sum;
    26 }
    27 void three_divide(int x)
    28 {
    29     l=max(x,n-x+1);r=0x7ffffffffffff;;int mid;
    30     while(l+2<r)
    31     {
    32          mid=l+(r-l)/3;int midd=r-(r-l)/3;
    33          if(work(mid,x)>work(midd,x))
    34          {
    35               l=mid;
    36          }
    37          else
    38               r=midd;
    39          //printf("l=%lld mid=%lld r=%lld
    ",l,mid,r);
    40     }
    41     for(int i=l;i<=r;++i)
    42     minn=min(minn,work(i,x));
    43 }
    44 signed main()
    45 {
    46     scanf("%lld",&n);
    47     for(int i=1;i<=n;++i)
    48     {
    49         scanf("%lld",&a[i]);
    50         max_r=max(max_r,a[i]);
    51     }
    52 
    53     for(int i=1;i<=n;++i)
    54     {
    55         three_divide(i);
    56     }
    57     printf("%lld
    ",minn);
    58 }
    View Code

    至于正解

    再次%%%%%skyh(用不是正解的方法碾压正解)

    第一次听说模拟退火,很神奇的随机化算法(以后骗分的好技巧2333333),

    然后就学了学,

    定义了几个量

    T初始化温度,esp最终温度,base变化倍数

    nowpos,nowans现在位置和答案,lastpos,lastans

    然后每次通过上一次位置随机化这一次的位置

    之后改变ans时一种是lastans更优另一种是

    (exp((lastans-nowans)/T)*RAND_MAX)>rand())

    一种我不太会证的定理......总之就是以一定的概率即使不优也要转移

    然后丑陋的代码

     1 #include<bits/stdc++.h>
     2 #define MAXN 100010
     3 #define ps push_back
     4 #define int long long
     5 using namespace std;
     6 double esp=1e-5,T=1000,base=0.975;
     7 int nowans,lastans;
     8 int nowpos,lastpos;
     9 int s[MAXN];int a[MAXN];
    10 int n;
    11 int ans=0x7fffffffffff;
    12 int find(int x)
    13 {
    14     int mid=(1+n)>>1;
    15     for(int i=1;i<=n;++i)s[i]=a[i]+abs(x-i);
    16     nth_element(s+1,s+mid,s+n+1);
    17     int cal=s[mid];
    18     cal=max(cal,max(x,n-x+1));
    19     int tot=0;
    20     for(int i=1;i<=n;++i)tot+=abs(cal-s[i]);
    21     return tot;
    22 }
    23 signed main()
    24 {
    25     srand(time(0));
    26     scanf("%lld",&n);
    27     for(int i=1;i<=n;++i)
    28     {
    29         scanf("%lld",&a[i]);
    30     }
    31     lastpos=(n+1)/2;
    32     lastans=find(lastpos);
    33     ans=min(ans,lastans);
    34     while(T>esp)
    35     {
    36         nowpos=lastpos+(2ll*rand()-RAND_MAX)*T*0.000001;
    37         if(nowpos<1)
    38         {
    39             nowpos=max(1ll,nowpos);
    40             nowpos=min(n,nowpos);
    41         }
    42         else
    43         {
    44             nowpos=(nowpos%n+n-1)%n+1;
    45         }
    46         nowans=find(nowpos);
    47         if(nowans<lastans||(exp((lastans-nowans)/T)*RAND_MAX)>rand())
    48         {
    49             lastans=nowans;
    50             lastpos=nowpos;
    51         }
    52         ans=min(ans,nowans);
    53         T*=base;
    54     }
    55     printf("%lld
    ",ans);
    56 }
    我没打正解,我没脸
     
  • 相关阅读:
    【转】每天一个linux命令(52):ifconfig命令
    【转】每天一个linux命令(51):lsof命令
    linux挂载SD卡
    【转】每天一个linux命令(50):crontab命令
    【转】每天一个linux命令(49):at命令
    【转】每天一个linux命令(48):watch命令
    【转】每天一个linux命令(47):iostat命令
    【转】每天一个linux命令(46):vmstat命令
    【转】每天一个linux命令(45):free 命令
    【转】每天一个linux命令(44):top命令
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11329612.html
Copyright © 2020-2023  润新知