C/C++教程

CF643G Choosing Ads

本文主要是介绍CF643G Choosing Ads,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

传送门


思路

先考虑一下 \(p > 50\) 的情况

这时候就是求“绝对众数”

一个方法就是用“摩尔投票”法

方法就是:每次将不同的两个数去掉,剩下的那种数就是绝对众数(这是保证在有的情况下,才能求出正确的众数)

再考虑 \(20\le p \le 50\) 时,其实我们可以维护 \(\lfloor\frac{p}{100}\rfloor\) 个这样的数

当新增一个数时,我们与维护的数进行比较:如果维护的数有与新增的数相同的,就将这种数的“个数”+1;否则,我们就所有维护的数的“个数”都减一,如果出现 \(-1\) 的,就用新增的数替代它

有区间赋值和询问,采用线段树维护即可

有个辣鸡因为把一个 \(i\) 打成 \(j\) 导致调了接近一个下午,我不说是谁


代码

#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define LL long long
#define FOR(i, x, y) for(int i = (x); i <= (y); i++)
#define ROF(i, x, y) for(int i = (x); i >= (y); i--)
#define PFOR(i, x) for(int i = he[x]; i; i = r[i].nxt)
inline int reads()
{
    int sign = 1, re = 0; char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
    while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
    return sign * re;
}
int n, m, p; int cnt;
struct Node
{
    int val[6], cnt[6], num; bool tag;
}tr[600005];
#define ls (now << 1)
#define rs ((now << 1) | 1)
inline void down(int now, int l, int r)
{
    if(tr[now].tag)
    {
        int mid = (l + r) >> 1;
        tr[ls].tag = tr[rs].tag = 1;
        tr[ls].num = tr[rs].num = 1;
        tr[ls].val[1] = tr[rs].val[1] = tr[now].val[1];
        tr[ls].cnt[1] = mid - l + 1, tr[rs].cnt[1] = r - mid;
        tr[now].tag = 0;
    }
}
inline Node merge(Node a, Node b)
{
    FOR(i, 1, a.num)
    {
        bool same = 0;
        FOR(j, 1, b.num)
            if(a.val[i] == b.val[j])
            {
                b.cnt[j] += a.cnt[i];
                same = 1;
                break;
            }
        if(same) continue;
        if(b.num < p)
        {
            ++b.num,
            b.val[b.num] = a.val[i],
            b.cnt[b.num] = a.cnt[i];
            continue;
        }
        int id = 1;
        FOR(j, 2, b.num)
            if(b.cnt[j] < b.cnt[id]) id = j;
        if(b.cnt[id] < a.cnt[i])
            std::swap(a.val[i], b.val[id]), std::swap(a.cnt[i], b.cnt[id]);
        FOR(j, 1, b.num)
            b.cnt[j] -= a.cnt[i];
    }
    b.tag = 0;
    return b;
}
void build(int now, int l, int r)
{
    if(l == r)
    {
        tr[now].val[1] = reads();
        tr[now].num = tr[now].cnt[1] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
    tr[now] = merge(tr[ls], tr[rs]);
}
void modify(int now, int l, int r, int L, int R, int val)
{
    if(L <= l && r <= R)
    {
        tr[now].val[1] = val;
        tr[now].num = 1;
        tr[now].cnt[1] = r - l + 1;
        tr[now].tag = 1;
        return;
    }
    down(now, l, r);
    int mid = (l + r) >> 1;
    if(L <= mid) modify(ls, l, mid, L, R, val);
    if(mid < R) modify(rs, mid + 1, r, L, R, val);
    tr[now] = merge(tr[ls], tr[rs]);
}
Node query(int now, int l, int r, int L, int R)
{
    if(L <= l && r <= R) return tr[now];
    down(now, l, r);
    int mid = (l + r) >> 1;
    if(R <= mid) return query(ls, l, mid, L, R);
    if(mid < L) return query(rs, mid + 1, r, L, R);
    return merge(query(ls, l, mid, L, R), query(rs, mid + 1, r, L, R));
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    n = reads(), m = reads(), p = reads(), p = 100 / p;
    build(1, 1, n);
    FOR(i, 1, m)
    {
        int ty = reads(), l = reads(), r = reads();
        if(ty == 1)
        {
            int val = reads();
            modify(1, 1, n, l, r, val);
        }
        else
        {
            cnt++;
            Node ans = query(1, 1, n, l, r);
            printf("%d ", ans.num);
            FOR(j, 1, ans.num) printf("%d ", ans.val[j]);
            puts("");
        }
    }
    return 0;
}
这篇关于CF643G Choosing Ads的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!