首页 > 编程语言 > 详细

BZOJ2743 HEOI2012采花(离线+树状数组)

时间:2018-09-08 13:38:48      阅读:172      评论:0      收藏:0      [点我收藏+]

  如果能够把所有区间内第二次出现某颜色的位置标记出来,树状数组查询一下就可以了。

  考虑离线。按左端点从小到大排序,不断移动左端点并更新第二次出现的位置。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<0||c>9) {if (c==-) f=-1;c=getchar();}
    while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 2000010
int n,m,c,a[N],nxt[N],p[N],tree[N],ans[N],flag[N];
struct data
{
    int l,r,i;
    bool operator <(const data&a) const
    {
        return l<a.l;
    }
}q[N];
void add(int k,int x){while (k<=n) tree[k]+=x,k+=k&-k;}
int sum(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj2743.in","r",stdin);
    freopen("bzoj2743.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read(),c=read(),m=read();
    for (int i=1;i<=n;i++)
    {
        a[i]=read(),nxt[p[a[i]]]=i,p[a[i]]=i;
        if (flag[a[i]]==1) add(i,1),flag[a[i]]=2;
        else if (!flag[a[i]]) flag[a[i]]=1;
    }
    for (int i=1;i<=n+1;i++) if (!nxt[i]) nxt[i]=n+1;
    for (int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].i=i;
    sort(q+1,q+m+1);
    q[0].l=1;
    for (int i=1;i<=m;i++)
    {
        while (q[i].l>q[i-1].l) 
        add(nxt[q[i-1].l],-1),add(nxt[nxt[q[i-1].l]],1),q[i-1].l++;
        ans[q[i].i]=sum(q[i].r)-sum(q[i].l-1);
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

 

BZOJ2743 HEOI2012采花(离线+树状数组)

原文:https://www.cnblogs.com/Gloid/p/9608875.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!