码迷,mamicode.com
首页 > 其他好文 > 详细

P1903 [国家集训队]数颜色 / 维护队列

时间:2018-10-15 23:21:15      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:code   国家   排序   swa   long   判断   lock   pow   clu   

毒瘤数据卡普通莫队!!

这道题跟普通的莫队题目差不多,但是多了一个修改操作。

所以带修莫队就横空出世了。

普通莫队记录左端点和右端点,那么这里就再记录一个时间轴,表示当时已经执行过几次修改。

之后莫队模板就有六个while,前四个是一样的。

最后两个判断当前修改次数和目标修改次数的关系。这个就是灵魂了。

重点看这个时间轴上的修改吧。

void change(int idx, int i)
{
    if(q[i].l <= c[idx].p && c[idx].p <= q[i].r)// 当修改点在询问区间内才需要维护答案
    {
        del(a[c[idx].p]);
        add(c[idx].col);
    }
    std::swap(a[c[idx].p], c[idx].col);// 很巧妙的一个操作,这样操作答案不变,程序更简洁
}

完整代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
const int maxn = 50005;
struct Query
{
    int l, r, id, pre;
} q[maxn];
int q_tot;
struct Change
{
    int p, col;
} c[maxn];
int c_tot;
int belong[maxn], block;
int a[maxn];
int out[maxn];
int n, m;

int l, r, res, changed;
int cnt[1000005];

bool cmp(Query x, Query y)// 按照左右端点所在块排序,再按时间排序
{
    if(belong[x.l] != belong[y.l]) return belong[x.l] < belong[y.l];
    if(belong[x.r] != belong[y.r]) return belong[x.r] < belong[y.r];
    return x.pre < y.pre;
}
int read()
{
    int ans = 0, s = 1;
    char ch = getchar();
    while(ch > ‘9‘ || ch < ‘0‘){ if(ch == ‘-‘) s = -1; ch = getchar(); }
    while(ch >= ‘0‘ && ch <= ‘9‘) ans = (ans << 3) + (ans << 1) + ch - ‘0‘, ch = getchar();
    return s * ans;
}
void add(int x)
{
    if(++cnt[x] == 1) res++;
}
void del(int x)
{
    if(--cnt[x] == 0) res--;
}
void change(int idx, int i)
{
    if(q[i].l <= c[idx].p && c[idx].p <= q[i].r)
    {
        del(a[c[idx].p]);
        add(c[idx].col);
    }
    std::swap(a[c[idx].p], c[idx].col);
}
void moqueue()
{
    block = pow(n, 0.6666667);// 块大小要换成这样
    for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1;
    std::sort(q + 1, q + q_tot + 1, cmp);
    l = 1, r = 0, res = 0, changed = 0;
    for(int i = 1; i <= q_tot; i++)
    {
        while(r < q[i].r) add(a[++r]);
        while(r > q[i].r) del(a[r--]);
        while(l > q[i].l) add(a[--l]);
        while(l < q[i].l) del(a[l++]);
        while(changed < q[i].pre) change(++changed, i);// 改少了
        while(changed > q[i].pre) change(changed--, i);// 改多了
        out[q[i].id] = res;
    }
}
int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    for(int i = 1; i <= m; i++)
    {
        char opt[3]; scanf("%s", opt);
        if(opt[0] == ‘Q‘)
        {
            int x = read(), y = read();
            q[++q_tot] = (Query){x, y, q_tot, c_tot};
        }
        else if(opt[0] == ‘R‘)
        {
            int p = read(), col = read();
            c[++c_tot] = (Change){p, col};
        }
    }
    moqueue();
    for(int i = 1; i <= q_tot; i++) printf("%d\n", out[i]);
    return 0;
}

P1903 [国家集训队]数颜色 / 维护队列

标签:code   国家   排序   swa   long   判断   lock   pow   clu   

原文地址:https://www.cnblogs.com/Garen-Wang/p/9794919.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!