• [HEOI2012]采花


    题目描述

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

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

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

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

    说明

    n,m,c210^6

    题解:

    一句话题意:求询问区间内出现次数大于1的数有多少个。

    直接处理不现实。可以离线。

    询问按照左端点排序。

    可以类比HH的项链、

    预处理每个点nxt[i],表示i位置相同颜色的下一个位置。

    树状数组每个点(点的值是c)为1的含义是,这个点在当前询问区间左端点为L的时候,是从L开始的第二个出现的这个数c

    开始把所有颜色第二次出现的位置+1

    那么对于所有的询问左端点为L的询问,直接query(r)-query(l-1)即可。

    可以理解,第三次及以上出现的不算重,一次的也不会算。必须r包含第二次出现的才会统计上。

    L右移的时候,把nxt[L]-=1,nxt[nxt[L]]+=1因为,nxt[L]原来是第二个,现在会变成第一个。

    nxt[nxt[L]]就变成第二个了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2000000+5;
    int n,m,c;
    int has[N],nxt[N];
    int a[N];
    int f[N];
    void add(int x,int d){
        for(;x<=n;x+=x&(-x)) f[x]+=d;
    }
    int query(int x){
        int ret=0;
        for(;x;x-=x&(-x)) ret+=f[x];return ret;
    }
    struct node{
        int l,r;
        int id;
        bool friend operator <(node a,node b){
            return a.l<b.l;
        }
    }q[N];
    int ans[N];
    int pos[N];
    int main()
    {
        scanf("%d%d%d",&n,&c,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            has[a[i]]++;
            if(pos[a[i]])nxt[pos[a[i]]]=i;
            if(has[a[i]]==2) add(i,1);
            pos[a[i]]=i;
        }
        int l,r;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }sort(q+1,q+m+1);
        int L=1;
        for(int i=1;i<=m;i++){
            while(L<q[i].l){
                if(nxt[L]) add(nxt[L],-1);
                if(nxt[nxt[L]]) add(nxt[nxt[L]],1);
                L++;
            }
            ans[q[i].id]=query(q[i].r)-query(q[i].l-1);
        }
        for(int i=1;i<=m;i++){
            printf("%d
    ",ans[i]);
        }
        return 0;
    }

    总结:
    对于离线区间询问的情况——BY LYD:

    1.cdq分治(对于前一半对后一半的影响)

    2.整体二分(对于答案)

    3.区间排序(对于处理答案先后顺序,便于区间之间转化的时候降低复杂度(经典的有如莫队))

  • 相关阅读:
    出现( linker command failed with exit code 1)错误总结 (转)
    iOS 面试题
    iOS 网络-深入浅出 -> 三方SDWebImage
    免费的论文查重网站
    关于GCD中单例的实现,不仅仅是 dispatch_once(视图完整版)
    Objective
    iOS 实现代码编写中 字典属性的可读性
    iOS Category 和 Protocol 中的 Property 你们真的会了么?
    iOS 中的观察者模式之通知中心
    iOS中的 观察者模式 之 KVO
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9676591.html
Copyright © 2020-2023  润新知