[HEOI2012] flowers (Fenwick tree) (summer D11)

The meaning of problems

The number of at least 2 times the number of request interval period occurs.

Guaranteed n- , m , C 2 * . 1 0 . 6 , a range C

answer

I talked about class time feel a little familiar, and later verses necklace of HH the variant, that this idea is worthy of note of it.

The first team practice is Mo, the operation is very simple, but time out.

Compare clever idea is, the right end point for the same query, if a number appears at least twice, then we only care where he appeared a second time, because if he appeared first position contains 3 times or more, it is must contain him, but only two can contribute, more contributions will not increase.

The sequence position index tree established as an array, for the second number occurs from right to left, in this position +1;

For queries with a right end point, and range queries it is.

When the right end point is moved, this number becomes the number first appears; for the first time before the number becomes the second occurrence number, for which the position +1; before the occurrence of a second number, which he became third appearance has no contribution to this position -1;

 

#include<bits/stdc++.h>
using namespace std;

const int maxn=2000005;
int n,m,c;
int pos[maxn],size;
int co[maxn],fir[maxn],sec[maxn];
int cx[maxn<<1];
int ans[maxn];
struct question{
    int l,r,id;
}q[maxn];

template<class T>inline void read(T &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

bool cmp(question a,question b){return a.r<b.r;}

void add(int x,int val){for(;x<=n;x+=x&-x) cx[x]+=val;}

int query(int x){
    int ret=0;
    for(;x;x-=x&-x) ret+=cx[x];
    return ret;
}

int main(){
    read(n);read(c);read(m);
    for(int i=1;i<=n;i++) read(co[i]);
    for(int i=1;i<=m;i++){read(q[i].l);read(q[i].r);q[i].id=i;}
    sort(q+1,q+m+1,cmp);
    int j=1;
    for(int i=1;i<=n;i++){
        if(!fir[co[i]])//这个数之前没出现
         fir[co[i]]=i;
        else if(!sec[co[i]]){//只有一个 
           add(fir[co[i]],1);
           sec[co[i]]=fir[co[i]];
           fir[co[i]]=i;
        }
        else {//出现了两次以上 
          add(sec[co[i]],-1);
          add(fir[co[i]],1);
          sec[co[i]]=fir[co[i]];
          fir[co[i]]=i;
        }
        while(q[j].r==i) ans[q[j].id]=query(q[j].r)-query(q[j].l-1),j++;
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
View Code

 

Guess you like

Origin www.cnblogs.com/sto324/p/11234613.html