[bzoj2743][HEOI2012]采花

来自FallDream的博客,未经允许,请勿转载,谢谢。


萧芸斓是Z国的公主,平时的一大爱好是采花。

今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴!同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了m个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案!),最后会选择令公主最高兴的行程(为了拿到更多奖金!)。
n,m<=10^6
 
也就是求区间数量大于1的颜色的个数。
考虑从左到右,维护每个左端点对应的答案。每次加入一个颜色c,last[last[c]]+1到last[c]的答案会+1,线段树维护即可。
#include<iostream>
#include<cstdio>
#include<vector>
#define pa pair<int,int>
#define mp(x,y) make_pair(x,y) 
#define MN 1000000
#define N 1048576
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n,c,m,Ans[MN+5],a[MN+5],last[MN+5],Last[MN+5],T[N*2+5];
vector<pa> v[MN+5];

inline int Query(int l,int r)
{
    int sum=0;
    for(l+=N-1,r+=N+1;l^r^1;l>>=1,r>>=1)
    {
        if(~l&1) sum+=T[l+1];
        if( r&1) sum+=T[r-1];    
    }
    return sum;
}

inline void Renew(int x,int ad)
{
    for(T[x+=N]+=ad,x>>=1;x;x>>=1)
        T[x]=T[x<<1]+T[x<<1|1];
}

int main()
{
    n=read();c=read();m=read();
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1;i<=m;++i)
    {
        int l=read(),r=read();
        v[r].push_back(mp(l,i));    
    }
    for(int i=1;i<=n;++i) 
    {
        if(last[a[i]]) Renew(Last[a[i]]+1,1),Renew(last[a[i]]+1,-1);
        Last[a[i]]=last[a[i]];last[a[i]]=i;
        for(int j=0;j<v[i].size();++j) Ans[v[i][j].second]=Query(1,v[i][j].first);
    }
    for(int i=1;i<=m;++i) printf("%d\n",Ans[i]);
    return 0;
}
posted @ 2017-05-25 17:55  FallDream  阅读(222)  评论(0编辑  收藏  举报