bzoj2743

http://www.lydsy.com/JudgeOnline/problem.php?id=2743

我们可以用树状数组 和1878很像

就是如果遇见了一个新的颜色,那么把他的前继+1 前继的前继 -1 然后扫描每个位置 这个位置为r的统计答案 因为这样能告诉你一个颜色最右端哪里可以取

#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
struct query {
    int l, r, id;
} q[N];
int n, m, color;
int c[N], tree[N], ans[N], pre[N][2];
bool cp(query i, query j) { return i.r < j.r; }
namespace bit
{
    int lowbit(int i) { return i & (-i); }
    void update(int pos, int delta)
    {
        for(int i = pos; i <= n; i += lowbit(i)) tree[i] += delta;
    }
    int ask(int pos)
    {
        int ret = 0;
        for(int i = pos; i; i -= lowbit(i)) ret += tree[i];
        return ret;
    }
} using namespace bit;
int main()
{
    scanf("%d%d%d", &n, &color, &m);
    for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
    for(int i = 1; i <= m; ++i) scanf("%d%d", &q[i].l, &q[i].r), q[i].id = i;
    sort(q + 1, q + m + 1, cp);
    int pos = 0;
    for(int i = 1; i <= m; ++i)
    {
        if(pre[c[i]][0]) update(pre[c[i]][0], 1);
        if(pre[c[i]][1]) update(pre[c[i]][1], -1);
        pre[c[i]][1] = pre[c[i]][0];
        pre[c[i]][0] = i;
        while(q[pos + 1].r == i) 
        {
            ++pos; ans[q[pos].id] = ask(q[pos].r) - ask(q[pos].l - 1);        
        }    
    }
    for(int i = 1; i <= m; ++i) printf("%d
", ans[i]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/19992147orz/p/6739757.html