• 训练日志13 (8.7)


    T1 旋转子段

      这道题。。

      我脑子进水了,一点点性质都没有看出来。

      最基本的性质就是每个点到达固定点的方案一样。什么叫方案一样?就是它只能通过一种操作到达,实际上就是指它有固定的旋转中心。想到这一点,60分就拿到了。

      考虑优化,这种做法哪里会出现问题呢?就是每次枚举旋转点时要枚举区间统计答案,而枚举区间的过程中又会有很多冗余计算,所以我们可以记录一下以某个点为坐标轴下,向两边扩展,只在ans改变处统计答案,用两个前缀和维护,一个统计旋转前固定点的个数,另一个代表旋转后。

      小弟不才。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<vector>
     4 #define HZOI std
     5 using namespace HZOI;
     6 const int N=1e6+5;
     7 int n,res,ans;
     8 int a[N],b[N],sm[N<<1];
     9 vector<int> vec[N<<1];
    10 inline void read(int &);
    11 inline int max(int a,int b) { return a>b?a:b; }
    12 int main()
    13 {
    14     int flag=0;
    15     read(n);
    16     for (int i=1; i<=n; ++i)
    17     {
    18         read(a[i]);
    19         if (a[i]==i) b[2*i]=1,++res;
    20         b[i*2]+=b[i*2-2];
    21         ++sm[a[i]+i];
    22         vec[a[i]+i].push_back(abs(a[i]*2-(a[i]+i)));
    23     }
    24     for (int i=1; i<=n*2; ++i)
    25     {
    26         sort(vec[i].begin(),vec[i].end(),greater<int>());
    27         for (int j=0; j<vec[i].size(); ++j)
    28         {
    29             int r=vec[i][j];
    30             ans=max(ans,b[n<<1]-b[i+r]+b[i-r-2]+sm[i]);
    31             --sm[i];
    32         }
    33     }
    34     printf("%d",ans);
    35 }
    36 inline void read(int &a)
    37 {
    38     char ch=getchar();
    39     for (a=0; ch<'0' or ch>'9';ch=getchar());
    40     for (;ch>='0' and ch<='9'; a=(a<<3)+(a<<1)+(ch^48),ch=getchar());
    41 }
    旋转子段

     

    T2 走格子

      大模拟,但也不是纯模拟。

      思路非常好,很新奇。

      对于每一个点,它可能通向上、下、左、右四个格子(如果是白格),如果想传送,必须要是走到一个墙边,再传送。题中要求的是最短距离,而不是说到达的位置,这不同与模拟,我们就想到了最短路。

      顺着最短路的思路往下想,如何建边?想一个点,最多与八个点连边(上、下、左、右、上墙、下墙、左墙、右墙),然后如何建图。对于一个点想要i传送到远点,那么它必须先要走到一个墙处,这时我们遇到了问题:最近的墙的位置并不好求。我们想,既然我们要用最短路,只要保证每一个点是最优距离就行了(意思是不用考虑走到其他点的贡献,这样的话会算重,而且不好求),我们考虑一下局部最优解,那就是一个点就沿直线走,走到它最近的墙,然后通过这面墙转移到另外三个墙。

    然而这只能算是yy出来的理想情况,处理要到的那个墙又是问题,具体操作,因为有Dij,我们不考虑走到的那堵墙再传到它本身是否需要花费(虽然这是合法的,但是这可以有效缩短代码量),也就是说,将走到的那个最近点和其他点一视同仁,都距离+1,这让不会使答案又误,毕竟是求的最短路,我只要保证每个点本身最优就可以了。

      n^2处理最近的墙,建边然后跑Dij,解决了。  

      小弟不才。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<queue>
      5 #include<algorithm>
      6 #define HZOI std
      7 using namespace HZOI;
      8 const int N=555;
      9 inline void read(int &);
     10 struct DIJ{
     11     int num,dis;
     12     friend bool operator < (DIJ a,DIJ b)
     13     {
     14         return a.dis>b.dis;
     15     }
     16 }poi[N*N<<1];
     17 int n,m;
     18 int mp[N][N],sx,sy,tx,ty;
     19 int ed[4][N*N],len[4][N*N];//左、上、右、下
     20 int tt,first[N*N],vv[N*N<<5],nx[N*N<<5],ww[N*N<<5];
     21 int v[N*N];
     22 int stpx[4]={-1,1,0,0},stpy[4]={0,0,-1,1};
     23 void Dij(int );
     24 inline void Add(int ,int ,int );
     25 int main()
     26 {
     27     read(n),read(m);
     28     for (int i=1; i<=n; ++i)
     29         for (int j=1; j<=m; ++j)
     30         {
     31             char ch=getchar();
     32             while (ch^'.' and ch^'#' and ch^'C' and ch^'F') ch=getchar();
     33             if (ch=='C') sx=i,sy=j;
     34             else if (ch=='F') tx=i,ty=j;
     35             else if (ch=='#') mp[i][j]=1;
     36         }
     37     for (int i=1,d; i<=n; ++i)
     38         for (int j=1; j<=m; ++j)
     39         {
     40             int id=(i-1)*m+j;
     41             if (mp[i][j]) continue;
     42             if (mp[i][j-1]) ed[0][id]=id,len[0][id]=0;
     43             else ed[0][id]=ed[0][id-1],len[0][id]=len[0][id-1]+1;
     44             if (mp[i-1][j]) ed[1][id]=id,len[1][id]=0;
     45             else ed[1][id]=ed[1][(i-2)*m+j],len[1][id]=len[1][(i-2)*m+j]+1;
     46         }
     47     for (int i=n,d; i; --i)
     48         for (int j=m; j; --j)
     49         {
     50             int id=(i-1)*m+j;
     51             if (mp[i][j]) continue;
     52             if (mp[i][j+1]) ed[2][id]=id,len[2][id]=0;
     53             else ed[2][id]=ed[2][id+1],len[2][id]=len[2][id+1]+1;
     54             if (mp[i+1][j]) ed[3][id]=id,len[3][id]=0;
     55             else ed[3][id]=ed[3][i*m+j],len[3][id]=len[3][i*m+j]+1;
     56         }
     57     for (int i=1; i<=n; ++i)
     58         for (int j=1; j<=m; ++j)
     59         {
     60             if (mp[i][j]) continue;
     61             int id=(i-1)*m+j,minn=0x3f3f3f3f;
     62             for (int k=0; k<4; ++k)
     63             {
     64                 if (!mp[i+stpx[k]][j+stpy[k]])
     65                     Add(id,(i+stpx[k]-1)*m+j+stpy[k],1);
     66                 minn=min(len[k][id],minn);
     67             }
     68             for (int k=0; k<4; ++k)
     69                 if (minn==len[k][id] and len[k][id]^0)
     70                     Add(id,ed[k][id],minn);
     71                 else if (minn^len[k][id])
     72                     Add(id,ed[k][id],minn+1); 
     73         }
     74     memset(v,0,sizeof(v));
     75     Dij((sx-1)*m+sy);
     76     if (poi[(tx-1)*m+ty].dis==0x3f3f3f3f) puts("no");
     77     else printf("%d
    ",poi[(tx-1)*m+ty].dis);
     78     return 0;
     79 }
     80 void Dij(int k)
     81 {
     82     priority_queue<DIJ> q;
     83     for (int i=1; i<=n; ++i)
     84         for (int j=1; j<=m; ++j)
     85             poi[(i-1)*m+j].dis=0x3f3f3f3f,
     86             poi[(i-1)*m+j].num=(i-1)*m+j;
     87     poi[k].dis=0;
     88     poi[k].num=k;
     89     q.push(poi[k]);
     90     while (!q.empty())
     91     {
     92         DIJ x=q.top();
     93         q.pop();
     94         int pnt=x.num,dtc=x.dis;
     95         v[pnt]=1;
     96         for (int i=first[pnt]; i; i=nx[i])
     97         {
     98             int ver=vv[i];
     99             if (v[ver]) continue;
    100             if (poi[ver].dis>dtc+ww[i])
    101             {
    102                 poi[ver].dis=dtc+ww[i];
    103                 q.push(poi[ver]);
    104             }
    105         }
    106     }
    107 }
    108 inline void Add(int u,int v,int w)
    109 {
    110     vv[++tt]=v,ww[tt]=w,nx[tt]=first[u],first[u]=tt;
    111 }
    112 inline void read(int &a)
    113 {
    114     char ch=getchar();
    115     for (a=0; ch<'0' or ch>'9';ch=getchar());
    116     for (;ch>='0' and ch<='9'; a=(a<<3)+(a<<1)+(ch^48),ch=getchar());
    117 }
    走格子

    T3 柱状图

      神仙题,数状数组的妙用。

      会了一点点,不过还是挂上巨神博客吧。

      还见识了一种玄学算法,模拟退火

      

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<ctime>
     5 #include<algorithm>
     6 #define int long long
     7 #define HZOI std
     8 using namespace HZOI;
     9 const int N=1e5+5,INF=1<<30;
    10 double T=0.001,delta=0.97,eps=1e-10;
    11 int n,ans,a[N],b[N],nowpos,nowans,newpos,newans;
    12 inline int Ask(int );
    13 signed main()
    14 {
    15     srand(time(0));
    16     ans=1e16;
    17     scanf("%lld",&n);
    18     for (int i=1; i<=n; ++i)
    19         scanf("%lld",&a[i]);
    20     nowpos=(n+1)>>1;
    21     nowans=Ask(nowpos);
    22     while (T>eps)
    23     {
    24 //        printf("T=%.12lf
    ",T);
    25         newpos=max(1ll,newpos);
    26         newpos=min(n,newpos);
    27         newans=Ask(newpos);
    28         if( newans<nowans or exp((newans-nowans)/T)*RAND_MAX<rand() ) 
    29             nowpos=newpos,nowans=newans;
    30         if (newans<ans) ans=newans;
    31         T*=delta;
    32     }
    33     printf("%lld",ans);
    34 }
    35 inline int Ask(int k)
    36 {
    37     int t=1,sm=0,mid=(n+1)>>1,maxx;
    38     b[k]=a[k];
    39     for (int i=k-1; i; --i)
    40         b[i]=a[i]+t,++t;
    41     t=1;
    42     for (int i=k+1; i<=n; ++i)    
    43         b[i]=a[i]+t,++t;
    44     nth_element(b+1,b+mid,b+n+1);
    45     maxx=max(b[mid],max(k,n-k+1));
    46     for (int i=1; i<=n; ++i) sm+=abs(maxx-b[i]);
    47     return sm;
    48 }
    柱状图(模拟退火i)

      


  • 相关阅读:
    BZOJ4237:稻草人
    BZOJ4009:[HNOI2015]接水果(整体二分版)
    BZOJ3745:[COCI2015]Norma
    BZOJ3110:[ZJOI2013]K大数查询(整体二分版)
    BZOJ2716:[Violet 3]天使玩偶
    BZOJ2527:[POI2011]Meteors
    BZOJ4170:极光
    BZOJ1901:Dynamic Rankings
    Python基础终极实战 基于C/S架构的仿优酷项目
    大白话五种IO模型
  • 原文地址:https://www.cnblogs.com/LH-Xuanluo/p/11324860.html
Copyright © 2020-2023  润新知