zoukankan      html  css  js  c++  java
  • NOIP模拟测试14

    以前的坑,填一下。

    写在前面的:以后我的考试感想将主要写自己的反思,题解之类的就略写了,主要能让我自己回忆起来就行。

    想看详细题解点这里 https://www.cnblogs.com/Gkeng,比我写的不知高到哪里去了。

    Problem A:旋转子段

    一对点反转后可以成为固定点,满足$a_i + i = a_j + j$.$a_i + i$可以确定一个反转区间的中心。

    我们把每个$a_i + i$扔到桶里,这里用vector。枚举区间中心,按区间长度把每个桶内排序,扫一遍用区间内固定点个数更新答案。

    这题没啥问题,实名谴责出题人假数据范围。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 1000005;
     4 int n, ori[N << 2], ans, sum[N << 2], pos;
     5 std::vector<int> v[N << 2];
     6 
     7 bool cmp(int x, int y) {
     8     return abs(pos - (x << 1)) < abs(pos - (y << 1));
     9 }
    10 
    11 signed main() {
    12     scanf("%d", &n);
    13     for (int i = 1; i <= n; i++) {
    14         scanf("%d", &ori[i]);
    15         sum[i] = sum[i - 1] + (ori[i] == i);
    16         v[i + ori[i]].push_back(i);
    17     }
    18     for (int i = 2; i <= (n << 1); i++) {
    19         if (v[i].empty()) continue;
    20         pos = i;
    21         std::sort(v[i].begin(), v[i].end(), cmp);
    22         int j = 1;
    23         for (auto k : v[i]) {
    24             int l = k, r = i - k;
    25             if (l > r) std::swap(l, r);
    26             ans = std::max(ans, sum[l - 1] + sum[n] - sum[r] + j), j++;
    27         }
    28     }
    29     return !printf("%d
    ", ans);
    30 }
    A

    Problem B:走格子

    初看以为就是BFS,发现限制很多。

    Portal可以直接等价于跑到离得最近的墙,建立Portal,就可以前往四个方向的任意一个墙。

    想到暴力建图跑最短路。预处理墙的位置更好做一点。

    本次考试以及OI生涯最大失误:把数据生成器错交到了OJ上。。。。。

    我都不知道我的脑子里都在想点啥。。。。。。。。

    以后提交之前必须check一下,100分白丢太痛苦,Rank 2 -> Rank 35

     1 #include <bits/stdc++.h>
     2 #define id(x, y) ((x - 1) * m + y)
     3 
     4 const int N = 500005, M = 505;
     5 int n, m, ecnt, head[N], st, ed, step[M][M], dis[N];
     6 int wall_l[M][M], wall_r[M][M], wall_u[M][M], wall_d[M][M];
     7 const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
     8 char matrix[M][M];
     9 struct Edge {int to, nxt, val;} e[N << 3];
    10 std::queue<std::pair<int, int> > q;
    11 bool vis[N];
    12 
    13 inline void addedge(int f, int to, int val) {
    14     e[++ecnt] = {to, head[f], val}, head[f] = ecnt;
    15 }
    16 
    17 void link(int x, int y) {
    18     if (matrix[x][y] != '.') return;
    19     if (matrix[x][y + 1] == '.') addedge(id(x, y), id(x, y + 1), 1), 
    20         addedge(id(x, y + 1), id(x, y), 1);;
    21     if (matrix[x + 1][y] == '.') addedge(id(x, y), id(x + 1, y), 1),
    22         addedge(id(x + 1, y), id(x, y), 1);
    23     if (wall_l[x][y] != id(x, y)) addedge(id(x, y), wall_l[x][y], step[x][y]);
    24     if (wall_r[x][y] != id(x, y)) addedge(id(x, y), wall_r[x][y], step[x][y]);
    25     if (wall_u[x][y] != id(x, y)) addedge(id(x, y), wall_u[x][y], step[x][y]);
    26     if (wall_d[x][y] != id(x, y)) addedge(id(x, y), wall_d[x][y], step[x][y]);
    27 }
    28 
    29 void Dij() {
    30     memset(dis, 0x3f, sizeof(dis));
    31     memset(vis, 0, sizeof(vis));
    32     std::priority_queue<std::pair<int, int> > que;
    33     dis[st] = 0;
    34     que.push(std::make_pair(0, st));
    35     while (!que.empty()) {
    36         int x = que.top().second;
    37         que.pop();
    38         if (vis[x]) continue;
    39         vis[x] = 1;
    40         for (int i = head[x], y = e[i].to; i; i = e[i].nxt, y = e[i].to) {
    41             if (dis[y] > dis[x] + e[i].val) {
    42                 dis[y] = dis[x] + e[i].val;
    43                 if (!vis[y]) que.push(std::make_pair(-dis[y], y));
    44             }
    45         }
    46     }
    47 }
    48 
    49 signed main() {
    50     scanf("%d%d", &n, &m);
    51     for (int i = 1; i <= n; i++) {
    52         scanf("%s", matrix[i] + 1);
    53         for (int j = 1; j <= m; j++) {
    54             if (matrix[i][j] == 'C') matrix[i][j] = '.', st = id(i, j);
    55             else if (matrix[i][j] == 'F') matrix[i][j] = '.', ed = id(i, j);
    56             else if (matrix[i][j] == '#') q.push(std::make_pair(i, j));
    57         }
    58     }
    59     
    60     while (!q.empty()) {
    61         int x = q.front().first, y = q.front().second;
    62         q.pop();
    63         for (int i = 0; i <= 3; i++) {
    64             int xx = x + dx[i], yy = y + dy[i];
    65             if (matrix[xx][yy] == '.' && !step[xx][yy]) {
    66                 step[xx][yy] = step[x][y] + 1;
    67                 q.push(std::make_pair(xx, yy));
    68             }
    69         }
    70     }
    71 
    72     for (int i = 1; i <= n; i++) {
    73         for (int j = 1; j <= m; j++) {
    74             if (matrix[i][j] != '.') continue;
    75             if (matrix[i][j - 1] == '#') wall_l[i][j] = id(i, j);
    76             else wall_l[i][j] = wall_l[i][j - 1];
    77             if (matrix[i - 1][j] == '#') wall_u[i][j] = id(i, j);
    78             else wall_u[i][j] = wall_u[i - 1][j];
    79         }
    80     }
    81     
    82     for (int i = n; i >= 1; i--) {
    83         for (int j = m; j >= 1; j--) {
    84             if (matrix[i][j] != '.') continue;
    85             if (matrix[i][j + 1] == '#') wall_r[i][j] = id(i, j);
    86             else wall_r[i][j] = wall_r[i][j + 1];
    87             if (matrix[i + 1][j] == '#') wall_d[i][j] = id(i, j);
    88             else wall_d[i][j] = wall_d[i + 1][j];
    89         }
    90     }
    91 
    92     for (int i = 1; i <= n; i++)
    93         for (int j = 1; j <= m; j++) link(i, j);
    94 
    95     Dij();
    96     if (dis[ed] == 0x3f3f3f3f) puts("no");
    97     else printf("%d
    ", dis[ed]);
    98     return 0;
    99 }
    B

    Problem C:柱状图

    $O(N^3)$暴力很好想,枚举位置,枚举高度,暴力计算,考场时间剩太少&贪正解,甚至这玩意都没打。

    $O(N^2)$需要动动脑子:我们要得到一个等差数列,可以直接给每一项减掉一个等差数列,再把它填平。可以想到填到处理后的中位数是最优的。

    它过不去。瓶颈在于答案的计算。可以去打那个树状数组的正解,把内层的N优化到log,我直接用退火优化掉了外层的N,优化到O(玄学)。

    一些人对退火有争议,我无法理解。用退火也没有什么问题,它和三分二分一样都是优化复杂度的工具,不存在什么骗AC的事情。而且本题答案(你原来要二分的那个东西,不是退火退的那个东西)必定单谷,这势必保证了退火实际效率能够吊打正解。

    爱说啥说啥吧,hhh。

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 
     4 const double eps = 0.1;
     5 const int N = 100005;
     6 int n;
     7 ll x[N], tmp[N], tmppos, nowpos, tmpans, nowans = 0x3f3f3f3f3f3f3f3f;
     8 double T = 100000;
     9 
    10 ll calc(int pos) {
    11     ll mx = std::max(n - pos, pos - 1);
    12     for (int i = 1; i <= n; i++) 
    13         tmp[i] = x[i] - mx + abs(i - pos);
    14     int mid = (1 + n) >> 1;
    15     ll ret = 0, mdzz = 0;
    16     std::nth_element(tmp + 1, tmp + mid, tmp + n + 1);
    17     mdzz = tmp[mid] > 0 ? tmp[mid] : 1;
    18     for (int i = 1; i <= n; i++) 
    19         ret += abs(mdzz - tmp[i]);
    20     return ret;
    21 }
    22 
    23 signed main() {
    24     srand(clock() + time(0));
    25     scanf("%d", &n);
    26     for (int i = 1; i <= n; i++)
    27         scanf("%lld", &x[i]);
    28     while (T > eps) {
    29         tmppos = ((int) (nowpos + (int) (T * ((double) rand()/ (double) RAND_MAX) * (rand() % 2 ? 1 : -1)) % n + n)) % n + 1;
    30         tmpans = calc(tmppos);
    31         ll delta = tmpans - nowans;
    32         if (delta < 0) 
    33              nowans = tmpans, nowpos = tmppos;
    34         else if (exp((double) -delta / T) * RAND_MAX > rand())
    35             nowpos = tmppos;
    36         T *= 0.976;
    37     }
    38     printf("%lld
    ", nowans);
    39     return 0;
    40 }
    C
  • 相关阅读:
    Objective-C Runtime 运行时之四:Method Swizzling
    App启动加载广告页面思路
    关于CoreData和SQLite多线程访问时的线程安全问题
    HIVE学习(待更新)
    流处理环境搭建
    CAJ2PDF
    ArcMap加载在线地图
    学习opencv(持续更新)
    风险和策略(待更新)
    区块链入门教程(转)
  • 原文地址:https://www.cnblogs.com/gekoo/p/11326863.html
Copyright © 2011-2022 走看看