洛谷 P1972 BZOJ 1878 [SDOI2009]HH的项链

简介: 题目描述 HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。

题目描述

HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH 不断地收集新的贝壳,因此,他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入输出格式

输入格式:

 

第一行:一个整数N,表示项链的长度。

第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。

第三行:一个整数M,表示HH 询问的个数。

接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。

 

输出格式:

 

M 行,每行一个整数,依次表示询问对应的答案。

 

输入输出样例

输入样例#1:
6
1 2 3 4 3 5
3
1 2
3 5
2 6
输出样例#1:
2
2
4

说明

数据范围:

对于100%的数据,N <= 50000,M <= 200000。

 

解题思路

  在线解法听说可以用主席树?那玩意太高端,本蒟蒻不会……

  离线解法主要有两种——一种是树状数组求前缀和的巧,另一种是分块莫队。我用的是前一种。

 

  离线,自然先把所有询问存下来,然后对所有询问按照左端点升序排序(右端点排不排无所谓的啦,反正又不影响结果)。

  然后记录下每种颜色的下一种相同颜色所在的位置,用next[i]表示。

  然后在树状数组中把每种颜色第一次出现的位置标记为1,然后就可以按排好的顺序处理所有询问了。

  一个个询问可以看作是一个滑动窗口在项链上滑动,读取窗口内的颜色信息。

  左端点的左边那些第一次出现的颜色就不能在区间中表示出来了,这是就要把左端点以左的标记为1颜色全部更新到下一个颜色相同的点上(next[i])。

  全定义一个变量l (模仿了黄学长的代码),表示目前已更新到第l个节点,那么每次统计答案之前肯定要把l一路更新到ask[i].l的前一位(没被标记为1的就不用更新了),这是询问的区间和就是答案啦!

----------------------------------------------------分割线-------------------------------------------------------

  我来填坑啦!并不会输公式,勉强看看吧

  莫队离线处理询问区间(li,ri),如果知道了(li,ri)的答案,那我们就能很快知道(li-1,ri)(li+1,ri)(li,ri-1)(li,ri+1)的答案,那么在已知(l[i],r[i])的答案的情况下,我们需要O(abs(l[i]-l[i+1])+abs(r[i]-r[i+1]))的时间暴力得到(l[i+1],r[i+1])的答案。如何使转移代价最少?一种方法是按曼哈顿最小生成树的dfs序转移,但是难度过高,于是——

  对于每个读入的询问(l[i],r[i]),我们设pos[i]=l[i]/sqrt(n),(这就是传说中的分块)以pos[i]为第一关键字,r[i]为第二关键字对所有询问进行排序,依次处理询问,这样能跑得很快。时间复杂度变成了O(n^(3/2))。

  证明和代码网上遍地都是,这里就不贴了(逃)。下面的代码思路是上面的。

源代码

#include<cstdio>
#include<algorithm>
#define lowbit(x) (x)&(-x)

int n,m,mx=-1;
int a[50010]={0},next[50010]={0};
int p[1000010]={0};//每种颜色出现的位置


int c[50010]={0};
int query(int pos)
{
    int ans=0;
    while(pos)
    {
        ans+=c[pos];
        pos-=lowbit(pos);
    }
    return ans;
}
void add(int pos,int x)
{
    while(pos<=n)
    {
        c[pos]+=x;
        pos+=lowbit(pos);
    }
}

struct Ask{
    int l,r,id,ans;
}ask[200010];
bool cmp1(const Ask & a,const Ask & b)
{
    return a.l==b.l?a.r<b.r:a.l<b.l;
}
bool cmp2(const Ask & a,const Ask & b)
{
    return a.id<b.id;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",a+i),mx=std::max(a[i],mx);
    for(int i=n;i>0;i--)
    {
        next[i]=p[a[i]];
        p[a[i]]=i;
    }
    for(int i=1;i<=mx;i++) if(p[i])add(p[i],1);
    
    scanf("%d",&m);
    for(int i=1,l,r;i<=m;i++)
    {
        scanf("%d%d",&l,&r);
        ask[i]={l,r,i,0};
    }
    
    std::stable_sort(ask+1,ask+1+m,cmp1);
    for(int i=1,ll=0;i<=m;i++)
    {
        while(ll<ask[i].l)
        {
            if(next[ll]) add(next[ll],1);
            ll++;
        }
        ask[i].ans=query(ask[i].r)-query(ask[i].l-1);
    }
    
    std::stable_sort(ask+1,ask+1+m,cmp2);
    for(int i=1;i<=m;i++)
        printf("%d\n",ask[i].ans);

    return 0;
}

 

目录
相关文章
|
6月前
|
算法
华为机试HJ76:尼科彻斯定理
华为机试HJ76:尼科彻斯定理
|
存储
洛谷P1972 [SDOI2009]HH的项链离线+树状数组)
洛谷P1972 [SDOI2009]HH的项链(离线+树状数组)
74 0
|
机器学习/深度学习
洛谷P5022 旅行(基环树+断环法)
洛谷P5022 旅行(基环树+断环法)
88 0
洛谷 P2827 BZOJ 4721 UOJ #264 蚯蚓
题目描述 本题中,我们将用符号表示对c向下取整,例如:。 蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。 蛐蛐国里现在共有n只蚯蚓(n为正整数)。
946 0
洛谷 P2486 BZOJ 2243 [SDOI2011]染色
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1、将节点a到节点b路径上所有点都染成颜色c; 2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
888 0
|
算法 vr&ar 人工智能
洛谷 P1972 [SDOI2009]HH的项链【莫队算法学习】
P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。
1142 0
|
人工智能 BI
洛谷 P3183 BZOJ 4562 [HAOI2016]食物链
题目描述 如图所示为某生态系统的食物网示意图,据图回答第1小题现在给你n个物种和m条能量流动关系,求其中的食物链条数。物种的名称为从1到n编号M条能量流动关系形如a1 b1a2 b2a3 b3......am-1 bm-1am bm其中ai bi表示能量从物种ai流向物种bi,注意单独的一种孤立生物不算一条食物链 输入输出格式 输入格式:   第一行两个整数n和m,接下来m行每行两个整数ai bi描述m条能量流动关系。
1007 0
洛谷 P1137 旅行计划
题目描述 小明要去一个国家旅游。这个国家有N个城市,编号为1~N,并且有M条道路连接着,小明准备从其中一个城市出发,并只往东走到城市i停止。 所以他就需要选择最先到达的城市,并制定一条路线以城市i为终点,使得线路上除了第一个城市,每个城市都在路线前一个城市东面,并且满足这个前提下还希望游览的城市尽量多。
767 0
|
算法 vr&ar 人工智能
BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】
2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 9894  Solved: 4561[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。
1543 0

热门文章

最新文章