• BZOJ2743:[HEOI2012]采花——题解


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

    萧薰儿是古国的公主,平时的一大爱好是采花。

    今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。

    花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴!同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。

    由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了m个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案!),最后会选择令公主最高兴的行程(为了拿到更多奖金!)。

    听说又是一道套路题……?还是HH的项链变形版?emm那不是个分块/莫队吗,这题数据范围这么大怎么做a……

    以及这题被某大佬标为0分sb题emmm……感觉到了深深的差距。

    参考:http://www.cnblogs.com/GXZlegend/p/6633834.html

    如果我们知道HH的项链如何用树状数组来做的话这题就异常简单了。

    我们将询问离线,然后从左往右扫,保证每种颜色出现第二次的位置标上1,这样我们询问$[l,r]$就相当于直接树状数组区间查询$[1,r]$的1的个数就行了。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=2e6+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct data{
        int l,r,id;
    }d[N];
    int n,m,c,b[N],tr[N],ans[N],lst[N],nxt[N];
    bool vis[N];
    inline bool cmp(data a,data b){
        return a.l<b.l;
    }
    inline int lowbit(int t){return t&-t;}
    inline void add(int x,int y){
        if(!x)return;
        for(int i=x;i<=n;i+=lowbit(i))tr[i]+=y;
    }
    inline int qry(int x){
        int res=0;
        for(int i=x;i;i-=lowbit(i))res+=tr[i];
        return res;
    }
    int main(){
        n=read(),c=read(),m=read();
        for(int i=1;i<=n;i++){
            b[i]=read();nxt[lst[b[i]]]=i;
            if(lst[b[i]]&&!vis[b[i]])vis[b[i]]=1,add(i,1);
            lst[b[i]]=i;
        }
        nxt[0]=0;
        for(int i=1;i<=m;i++){
            d[i].l=read(),d[i].r=read();
            d[i].id=i;
        }
        sort(d+1,d+m+1,cmp);
        for(int i=1,j=1;i<=n;i++){
            add(nxt[i-1],-1);add(nxt[nxt[i-1]],1);
            while(d[j].l==i){
                ans[d[j].id]=qry(d[j].r);
                j++;
            }
        }
        for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    Javaoop_继承
    事务,视图,索引,备份和恢复
    常用函数。
    为虚拟机配置NAT网络
    安装Linux系统
    初始Redis
    高内聚低耦合
    MyBatis动态SQL
    初始MyBatis
    GitHub的操作
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9211949.html
Copyright © 2020-2023  润新知