2020 CCPC绵阳 J K

J. Joy of Handcraft

题意:

给定 n 个灯泡的时间周期以及对应的亮度值,求 1 ~ m 的时刻,每一时刻的灯泡最大亮度

分析:

按时间轴建树,维护时间区间的亮度最大值
按亮度值递减排序,遍历灯泡时只 modify 为相同周期中亮度值最大的一个灯泡作为区间亮度最大值
区间修改,单点查询

实现:

#include <bits/stdc++.h>
using namespace std;
#define mst(x, y) memset(x, y, sizeof x)
#define endl '\n'
#define INF LONG_LONG_MAX
#define int long long
#define Lson u << 1, l, mid
#define Rson u << 1 | 1, mid + 1, r
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 200010, MOD = 1e9 + 7;
const double EPS = 1e-6;
typedef pair<int, int> PII;
int T;
int n, m;
int Case = 1;
bool st[N];
struct Q
{
    int t, x;
} q[N];
struct Node
{
    int l, r;
    int val;
    int lz;
} tr[N << 2];
void pushup(Node u, Node l, Node r)
{
    u.val = max(l.val, r.val);
}
void pushup(int u)
{
    pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void pushdown(int u)
{
    tr[u << 1].lz = max(tr[u].lz, tr[u << 1].lz);
    tr[u << 1 | 1].lz = max(tr[u].lz, tr[u << 1 | 1].lz);
    tr[u << 1].val = max(tr[u << 1].val, tr[u].lz);
    tr[u << 1 | 1].val = max(tr[u << 1 | 1].val, tr[u].lz);
    tr[u].lz = 0;
}
void build(int u, int l, int r)
{
    if (l == r)
        tr[u] = {l, l, 0, 0};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(Lson), build(Rson);
        pushup(u);
    }
}
void modify(int u, int l, int r, int k)
{
    if (tr[u].l >= l && tr[u].r <= r)
    {
        tr[u].lz = max(tr[u].lz, k);
        tr[u].val = max(tr[u].val, tr[u].lz);
    }
    else
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid)
            modify(u << 1, l, r, k);
        if (r > mid)
            modify(u << 1 | 1, l, r, k);
        pushup(u);
    }
}
int query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)
        return tr[u].val;
    else
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid)
            return query(u << 1, l, r);
        else
            return query(u << 1 | 1, l, r);
    }
}
void solve()
{
    mst(st, false);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> q[i].t >> q[i].x;
    sort(q + 1, q + 1 + n, [&](Q a, Q b)
         { return a.x > b.x; });

    build(1, 1, m);

    for (int i = 1; i <= n; i++)
    {
        if (st[q[i].t])
            continue;
        st[q[i].t] = true;

        int l = 1, r = q[i].t;
        while (l <= m)
        {
            // int tmp = query(1, l, min(r, m));
            // if (tmp < q[i].x)
                modify(1, l, min(r, m), q[i].x);
            l += 2 * q[i].t, r += 2 * q[i].t;
        }
    }

    for (int i = 1; i <= m; i++)
    {
        cout << query(1, i, i) << " \n"[i == m];
    }
}
signed main()
{
    FAST;
    T = 1;
    cin >> T;
    while (T--)
    {
        cout << "Case #" << Case++ << ": ";
        solve();
    }
    return 0;
}

K. Knowledge is Power

题意:

将一个数拆成若干个数使得每个数都不一样且两两互质,求差的最大值

分析:

关于两数互质:

  1. 两个数都是质数,这两个数互质
  2. 两个连续的自然数互质。如:8和9、14和15
  3. 两个连续的奇数互质。如7和9、11和13
  4. 两个不连续的奇数但只相隔一个奇数的两个数互质。如13和17、15和19
  5. 两个合数不含相同质因子的两数互质。如:4和9,6和25
  6. 1和任意一个自然数互质。如:1和8,1和50
  7. 2、4或8和任意一个奇数互质,如:2和9,4和21
  8. 3、7或11和任一个不成倍数关系的两数互质。如:3和11,7和25,11和14
  9. 5和另一个末尾非0非5的数互质,如:5和12,5和18
  10. 一个质数和一个合数,如质数大于合数,则两数互质;如合数大于质数,但不是质数倍的数,两数也互质。如:89和42,97和27,47和95,61和180

  • 如果x是奇数,那么拆分为x/2和x-x/2,答案是1
  • 如果x是偶数并且x/2是偶数,,那么可以分成x/2+1,x/2-1这是分成了两个奇数,一定互质,答案是2
  • 如果x是偶数并且x/2是奇数,那么我们对x取余3进行判断。
  • 如果是3的倍数,比如42,可以拆成13 14 15.那么答案是2
  • 如果取模3后余1,比如70 可以分成22 23 25 答案是3
  • 取模3余2,比如62 可以分成19 21 22 答案是3,按照上面构造方式 判断一下是不是两两互质即可,容易发现答案最多为4,因为如果x是偶数,x/2是奇数,那么只需要拆分为x/2-2、x/2+2即可
  • 注意特判x=6时候无解

实现:

#include <bits/stdc++.h>
using namespace std;
#define mst(x, y) memset(x, y, sizeof x)
#define endl '\n'
#define INF LONG_LONG_MAX
#define int long long
#define Lson u << 1, l, mid
#define Rson u << 1 | 1, mid + 1, r
#define FAST ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int N = 2000010, MOD = 1e9 + 7;
const double EPS = 1e-6;
typedef pair<int, int> PII;
int T;
int n, res;
int Case = 1;
bool check(int a, int b, int c)
{
    if (__gcd(a, b) == 1 && __gcd(a, c) == 1 && __gcd(b, c) == 1)
        return true;
    return false;
}
void solve()
{
    res = 4;
    cin >> n;
    if (n == 6)
        res = -1;
    else if (n & 1)
        res = 1;
    else
    {
        int k = n / 2;
        if (k % 2 == 0)
            res = 2;
        else
        {
            if (n % 3 == 0)
                res = 2;
            else if (n % 3 == 1)
            { // 70
              // 22 23 25
                int a = n / 3, b = a + 2, c = a - 1;
                if (check(a, b, c))
                    res = 3;
                else
                    res = 4;
            }
            else
            { // 62
              // 19 21 22
                int a = n / 3 - 1, b = a + 2, c = a + 3;
                if (check(a, b, c))
                    res = 3;
                else
                    res = 4;
            }
        }
    }
    cout << res << endl;
}
signed main()
{
    FAST;
    T = 1;
    cin >> T;
    while (T--)
    {
        cout << "Case #" << Case++ << ": ";
        solve();
    }
    return 0;
}
posted @ 2023-05-16 13:38  347Foricher  阅读(24)  评论(0编辑  收藏  举报