[BZOJ 2743] 采花

Posted NewErA

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 2743] 采花相关的知识,希望对你有一定的参考价值。

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

 

Algorithm:

此题询问区间内出现次数超过1个的数字

明显在线做无从下手,无法在区间两端都不确定的情况下统计符合要求的数字

 

但可以发现,如果左端确定,是可以用树状数组维护右端数据的

于是我们采取离线方式,将询问排序,左端点不断右移,树状数组随之更新即可

 

Code:

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
typedef pair<P,int> PP;
#define F first
#define S second

const int MAXN=1000010;
int dat[MAXN],bit[MAXN],res[MAXN],nxt[MAXN],cur[MAXN],fst[MAXN],n,c,m;
PP op[MAXN];

inline int read()
{
    char ch;int num,f=0;
    while(!isdigit(ch=getchar())) f|=(ch==-);
    num=ch-0;
    while(isdigit(ch=getchar())) num=num*10+ch-0;
    return f?-num:num;
}

inline void write(long long x)
{
    if(x<0) putchar(-),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+0);
}

void update(int pos,int x)
{
    while(pos<=n)
    {
        bit[pos]+=x;
        pos+=pos&(-pos);
    }
}

int cal(int pos)
{
    int ret=0;
    while(pos)
    {
        ret+=bit[pos];
        pos-=pos&(-pos);
    }
    return ret;
}

int main()
{
    n=read();c=read();m=read();
    fill(nxt,nxt+MAXN,MAXN-2);
    for(int i=1;i<=n;i++) dat[i]=read();
    for(int i=1;i<=m;i++) op[i].F.F=read(),op[i].F.S=read(),op[i].S=i;
    for(int i=1;i<=n;i++)
    {
        if(!cur[dat[i]]) fst[dat[i]]=i;
        nxt[cur[dat[i]]]=i,cur[dat[i]]=i;
    }
    for(int i=1;i<=c;i++) if(nxt[fst[i]]) update(nxt[fst[i]],1);
    
    nxt[0]=0;op[0].F.F=1;
    sort(op+1,op+m+1);
    
    for(int i=1;i<=m;i++)
    {
        for(int j=op[i-1].F.F;j<op[i].F.F;j++)
            update(nxt[nxt[j]],1),update(nxt[j],-1);
        res[op[i].S]=cal(op[i].F.S)-cal(op[i].F.F-1);
    }
    
    for(int i=1;i<=m;i++) write(res[i]),putchar(\n);
    return 0;
}

 

以上是关于[BZOJ 2743] 采花的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2743: [HEOI2012]采花

[bzoj2743][HEOI2012]采花(树状数组+离线)

BZOJ_2743_[HEOI2012]采花_离线+树状数组

[BZOJ 2743] 采花

bzoj2743[HEOI2012]采花

BZOJ-2743: [HEOI2012]采花(树状数组 or TLE莫队)