CF 351D - Jeff and Removing Periods(离线 + 树状数组)

来源:互联网 发布:js用偶数奇数隔行变色 编辑:程序博客网 时间:2024/05/20 16:43

题目链接:Click here~~

题意:

给一个长度为 n 的序列,Q 次询问,每次查询 [l,r] 中有多少个不同的数字,且是否存在一个数字,其出现的位置成等差数列。

解题思路:

接上篇继续刷离线查询题目。昨天想了1天,今天早上在床上想出思路了,2333333。

对于区间中不同数字的个数,可以用类似上篇的做法,c[j] 维护 [j,i] 中不同数字的个数,那么每次在位置 i 出现一个 v ,只需 [last_pos_v+1,i] 的值加 1 。

对于是否有数字的位置成等差数列,就不太好想,其实还可以用类似的方法搞。

cc[j] 维护 [j,i] 中位置成等差数列的数字的个数,每次在位置 i 出现一个 v,那么一定可以将区间 [last_pos_v+1,i] 的值加 1。

再快速找出 v 向前能延伸到的  满足位置成等差数列的  最远位置,如果这个位置比 v 上一次延伸到的位置近,那么给那段相应的区间的值减 1 就行了。

#include <vector>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int N = 1e5 + 5;struct BIT{    int c[N];    void init(){        memset(c,0,sizeof(c));    }    int lowbit(int x){        return x & -x;    }    void add(int loc,int val){        while(loc < N){            c[loc] += val;            loc += lowbit(loc);        }    }    void add(int a,int b,int val){        if(a > b)            return ;        add(a,val);        add(b+1,-val);    }    int sum(int loc){        int ret = 0;        while(loc){            ret += c[loc];            loc -= lowbit(loc);        }        return ret;    }}T1,T2;struct QAQ{    int l,r,id;    QAQ(){}    QAQ(int l,int r,int i):l(l),r(r),id(i){}    bool operator < (const QAQ& B) const{        return r < B.r;    }}query[N];int a[N],extend[N],ans[N];vector<int> pos[N];int main(){    int n,Q;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i]);    for(int i=1;i<N;i++)        pos[i].push_back(0);    scanf("%d",&Q);    for(int i=0;i<Q;i++)    {        int l,r;        scanf("%d%d",&l,&r);        query[i] = QAQ(l,r,i);    }    sort(query,query+Q);    int j = 0;    for(int i=1;j<Q && i<=n;i++)    {        int v = a[i];        pos[v].push_back(i);        int p = (int)pos[v].size() - 1;        T2.add(pos[v][p-1]+1,i,1);        if(p == 1)            extend[i] = 1;        else        {            if(p == 2 || pos[v][p] - pos[v][p-1] == pos[v][p-1] - pos[v][p-2])                extend[i] = extend[ pos[v][p-1] ];            else            {                extend[i] = pos[v][p-2] + 1;                T2.add(extend[ pos[v][p-1] ],extend[i]-1,-1);            }        }        T1.add(pos[v][p-1]+1,i,1);        while(j < Q && query[j].r == i)        {            ans[ query[j].id ] = T1.sum(query[j].l) + ( T2.sum(query[j].l) ? 0 : 1);            j++;        }    }    for(int i=0;i<Q;i++)        printf("%d\n",ans[i]);    return 0;}