刷题记录(NC20545 [HEOI2012]采花)(树状数组)

NC20545 [HEOI2012]采花

题目链接

关键点:

1、题目要求求出能采到花的颜色数。

2、记下每种颜色的前一个位置,和前前个位置。当一朵花第一次出现时,我们将其当作该种花前前个位置。当一朵花出现第二次时,将该位置当作该种花前一个位置。并且说明所有包含前前个花的区间都可以采该颜色的花,所以颜色数+1。当一朵花出现三次以上时,我们将包含前一朵花的区间+1,因为如果左区间从前一朵花开始,到当前这朵花结束,刚刚好为两朵花,那么颜色数可以+1。而对于包含前前朵花的区间则要-1,不然颜色就会重复计算

3、我们将所求的区间按照右区间排序,从小到大开始求,最后记得要按照题目给的顺序输出答案

# include <bits/stdc++.h>
using namespace std;
const int N = 10000000+10;
int res[N];
int ans[N];
int a[N];
int n, c, m;
int mp1[N], mp2[N];
struct ty{
    int l, r, id;
}t[10000000+10];
bool cmp(ty t1, ty t2)
{
    return t1.r < t2.r;
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int p, int x)
{
    while (p<=n)
    {
        res[p] += x;
        p += lowbit(p);
    }
}
int calc(int p)
{
    int sum = 0;
    while (p>0)
    {
        sum += res[p];
        p -= lowbit(p);
    }
    return sum;
}
int main()
{
    scanf("%d%d%d", &n, &c, &m);
    for (int i=1; i<=n; i++)
    {
        scanf("%d", &a[i]);
    }
    while (lowbit(n) != n) n+=lowbit(n);
    for (int i=1; i<=m; i++)
    {
        t[i].id = i;
        scanf("%d%d", &t[i].l, &t[i].r);
    }
    sort(t+1, t+1+m, cmp);
    int j = 1;
    for (int i=1; i<=m; i++)
    {
        for (; j<=t[i].r; j++)
        {
            if (!mp1[a[j]]) mp1[a[j]] = j;
            else{
                if (!mp2[a[j]])
                {
                    add(mp1[a[j]], 1);
                    mp2[a[j]] = j;
                }
                else
                {
                    add(mp2[a[j]], 1);
                    add(mp1[a[j]], -1);
                    mp1[a[j]] = mp2[a[j]];
                    mp2[a[j]] = j;
                }
            }
        }
        ans[t[i].id] = calc(t[i].r) - calc(t[i].l-1);
    }
    for (int i=1; i<=m; i++)
        printf("%d\n", ans[i]);
    
    
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值