bzoj 2743 分类: bzoj 2015-08-07 18:22 9人阅读 评论(0) 收藏


这道题的方法虽然应用不广,但很有意思。


主要是维护起始点固定时,每个结束点的答案

每个点记录下一个与它颜色相同的点的位置,记为next[]。

首先对于所有首次出现的点 x,将 next[x] ~ n 的答案都增加 1
然后就得到了当起始点为1时,每个结束点的答案。

如果起始点pos向右移动,next[pos]~next[next[pos]] - 1 的答案都减少 1

对答案改变的的操作可以用树状数组。。。


本来想用莫队水过的。。。然而TLE了


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    if(!sl) {putchar('0');return;}
    while(sl) putchar(s[--sl]);
}
const int size = 1e6 + 5, maxm = size, maxn = size;

int n, c, m, a[maxn];
int next[size], fir[size], tree[maxn];

struct type_query
{
    int id, l, r, ans;

    void scan(int __i)
    {
        id = __i, read(l), read(r);
    }
}query[maxm];

bool cmp(const type_query &a, const type_query &b){ return a.l < b.l;}
bool cmpid(const type_query &a, const type_query &b){ return a.id < b.id;}

#define lowbit(x) ((x)&-(x))
void add(int x,int val)
{
    if(!x) return;

    while(x <= n)
    {
        tree[x] += val;
        x += lowbit(x);
    }
}
int count(int x)
{
    int ret = 0;

    while(x > 0)
    {
        ret += tree[x];
        x -= lowbit(x);
    }
    return ret;
}
#undef lowbit

int main()
{
#ifndef ONLINE_JUDGE
    freopen("2743.in","r",stdin);
    freopen("2743.out","w",stdout);
#endif

    read(n), read(c), read(m);

    for(int i = 1; i <= n; i++) read(a[i]);
    for(int i = 1; i <= m; i++) query[i].scan(i);

    std::sort(query + 1, query + m + 1, cmp);

    for(int i = n; i >= 1; i--)
        next[i] = fir[a[i]], fir[a[i]] = i;

    for(int i = 1; i <= n; i++)
        if(fir[a[i]] == i) add(next[i], 1);

    for(int i = 1, pos = 1; i <= m; i++)
    {
        while(pos < query[i].l)
        {
            add(next[pos], -1);
            add(next[next[pos]], 1);
            pos ++;
        }
        query[i].ans = count(query[i].r);
    }   

    std::sort(query + 1, query + m + 1, cmpid);

    for(int i = 1; i <= m; i++)
        write(query[i].ans), puts("");

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-08-07 18:22  <Dash>  阅读(139)  评论(0编辑  收藏  举报