zoukankan      html  css  js  c++  java
  • [SCOI2009]生日礼物

    这道题很容易看出是一道单调队列题。

    首先我们根据珠子的位置排序。

    然后按顺序枚举一个个珠子。

    如果该种珠子没有出现过标记上它的位置,如果出现过修改并打上当前位置。当所有珠子都出现后,将当前位置减去打标记位置最小的一个即为当前解。

    可以证明正确性。

    显然选择珠子越靠后越好。

    最小位置的查找要$O(K)$,所以复杂度为$O(NK)$。

    这道题$K$比较小,该复杂度能过。但当$K$较大时会超时。

    我们充分运用单调队列的性质,牺牲空间换取时间。

    具体做法就是开一个数组记录第$i$个珠子是否在标记中,然后用一个指针$P$记录位置最小的珠子。

    珠子只会从前往后打上标记,所以当取消珠子的标记时,根据需要向后移动$P$指针直到再一次指向位置最小的珠子即可。

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define re register
     6 #define rep(i, a, b) for (re int i = a; i <= b; ++i)
     7 #define repd(i, a, b) for (re int i = a; i >= b; --i)
     8 #define maxx(a, b) a = max(a, b);
     9 #define minn(a, b) a = min(a, b);
    10 #define LL long long
    11 #define inf (1 << 30)
    12 
    13 inline int read() {
    14     int w = 0, f = 1; char c = getchar();
    15     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
    16     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();
    17     return w * f;
    18 }
    19 
    20 const int maxn = 1e6 + 5, maxk = 60 + 5;
    21 
    22 struct Ball {
    23     int k, p;
    24 } A[maxn];
    25 bool cmp(Ball a, Ball b) {
    26     return a.p < b.p;
    27 }
    28 
    29 int loc[maxk], N, K, tag[maxn];
    30 
    31 int main() {
    32     N = read(), K = read();
    33 
    34     int P = 0;
    35     rep(i, 1, K) {
    36         int T = read();
    37         rep(x, 1, T) A[++P] = (Ball){i, read()};
    38     }
    39     sort(A+1, A+N+1, cmp);
    40     P = 0;
    41     int cnt = 0, ans = (1<<31)-1;
    42     memset(tag, 0, sizeof(tag));
    43     rep(i, 1, N) {
    44         tag[loc[A[i].k]] = 0;
    45         if (!loc[A[i].k]) cnt++;
    46         loc[A[i].k] = i;
    47         tag[loc[A[i].k]] = 1;
    48         while (!tag[P]) P++;
    49         if (cnt == K) minn(ans, A[i].p - A[P].p);
    50     }
    51     printf("%d", ans);
    52     return 0;
    53 }
  • 相关阅读:
    第五章 运输层(UDP和TCP三次握手,四次挥手分析)
    Fluent Ribbon 第六步 StartScreen
    Fluent Ribbon 第七步 状态栏
    Fluent Ribbon 第八步 其他控件
    Avalondock 第四步 边缘停靠
    node.js开发学习一HelloWorld
    Winform应用程序实现通用遮罩层
    输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的
    Navicat连接MySQL8+时出现2059报错
    win10安装MySql教程
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10350916.html
Copyright © 2011-2022 走看看