树状数组--P1972 [SDOI2009]HH的项链

题目描述

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

有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答…… 因为项链实在是太长了。于是,他只好求助睿智的你,来解决这个问题。

输入格式

一行一个正整数 n,表示项链长度。
第二行 n 个正整数 ai?,表示项链中第 iii 个贝壳的种类。

第三行一个整数 m,表示 HH 询问的个数。
接下来 m 行,每行两个整数 l,r,表示询问的区间。

输出格式

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

1.按r排序一下
2.树状数组tree[j]维护从1到j不同数字的个数有多少个
3.然后用前缀和思想(tree[r]-tree[l-1])

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 #define maxn 1000009
 7 int num[maxn],tree[maxn],flag[maxn],tmp[maxn],N,w;
 8 using namespace std;
 9 inline int read()
10 {
11     int x = 1,a = 0;
12     char ch = getchar();
13     while(ch < ‘0‘ || ch > ‘9‘){
14         if(ch == ‘-‘)x = -1;
15         ch = getchar();
16     }
17     while(ch <= ‘9‘&&ch >= ‘0‘){
18         a = a * 10 + ch - ‘0‘;
19         ch = getchar();
20     }
21     return x*a;
22 }
23 struct node
24 {
25     int l,r;
26     int pos;
27 };
28 node ask[maxn];
29 inline bool cmp(node x,node y)
30 {
31     return x.r<y.r;
32 }
33 inline void add(int n,int now)
34 {
35     for (register int i = n;i <= N;i+=i&(-i))
36     {
37         tree[i]+=now;
38     }
39 }
40 inline int sum(int n)
41 {
42     int ans=0;
43     for (register int i = n;i;i-=i&(-i))
44     {
45         ans+=tree[i];
46     }
47     return ans;
48 }
49 int main()
50 {
51         N=read();
52         for(register int i=1;i<=N;i++)
53             num[i]=read();
54         w=read();
55         for(register int i=1;i<=w;i++)
56         {
57            ask[i].l=read();
58            ask[i].r=read();
59             ask[i].pos=i;
60         }
61         sort(ask+1,ask+1+w,cmp);
62         int next=1;
63         for(register int i=1;i<=w;i++)
64         {
65             for(register int j=next;j<=ask[i].r;j++)
66             {
67                 if(flag[num[j]])
68                     add(flag[num[j]],-1);
69                 add(j,1);
70                 flag[num[j]]=j;
71             }
72             next=ask[i].r+1;
73             tmp[ask[i].pos]=sum(ask[i].r)-sum(ask[i].l-1);
74         }
75     for(register int i=1;i<=w;i++)
76       cout<<tmp[i]<<endl;
77     return  0;
78 }

原文地址:https://www.cnblogs.com/very-beginning/p/12248758.html

时间: 2024-10-13 10:20:36

树状数组--P1972 [SDOI2009]HH的项链的相关文章

「树状数组」[SDOI2009]HH的项链

[SDOI2009]HH的项链 原题链接 [SDOI2009]HH的项链 题目大意 给你 \(n\) 个数,再给你 \(q\) 次询问,每次询问给你 \(l, r\) ,问你 \(l, r\) 中有多少个不同的数 题目题解 分析这道题我们发现,对于一个 \([L_1, R_1]\) 存在另一个 \([L_2, R_1]\) 且 \(L_2\) 严格大于 \(L_1\),那么就一定存在第一个区间不同的数 大于等于 第二个区间的不同的数,这里很显然有一种等于的情况,什么情况等于?在\([L_2,R_

P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链 2017-09-18 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答--因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行:N 个整

luogu P1972 [SDOI2009]HH的项链

二次联通门 : luogu P1972 [SDOI2009]HH的项链 /* luogu P1972 [SDOI2009]HH的项链 莫队水过 记录一个count数组 来记录每个数出现了几次 缩小区间时只要看是否只出现一次 扩张区间时只要看看是否出现过即可 */ #include <algorithm> #include <cstdio> #include <cmath> #define Max 1000001 void read (int &now) { no

洛谷 P1972 [SDOI2009]HH的项链

P1972 [SDOI2009]HH的项链 题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行:N 个整数,表示

luogu P1972 [SDOI2009]HH的项链 树状数组

之前只做过分块做法,补一下树状数组做法. 我们先考虑一个问题,如何求从[1,x]这一区间内元素不同的个数?显然我们只要从到到位,遇到一个新的元素,就在对应位置+1,然后使用树状数组求前缀和即可. 这里我们需要去求[x,y],所求区间的左端点也会发生变化.我们先按照[1,x]的方法预处理出这个前缀和数组.我们考虑对询问区间按照左端点排序.然后对于当前的区间[x0,y0],query(y0) - query(x0 - 1)与正确答案相比有所区别,是因为有些元素在x0左侧计算过了,而在这段区间中,对应

【题解】Luogu P1972 [SDOI2009]HH的项链

原题传送门 莫队入门题 我博客里对莫队的介绍 很多人说这题卡莫队,但窝随便写了一个程序就过了qaq(虽说开了氧化) 我们在排序询问时,普通是这样qaq inline bool cmp(register query a,register query b) { return a.bl==b.bl?a.r<b.r:a.bl<b.bl; } 我们要奇偶优化:按奇偶块排序.如果区间左端点所在块不同,那么就直接按左端点从小到大排:如果相同,奇块按右端点从小到大排,偶块按右端点从大到小排. inline b

SP3267 DQUERY - D-query(离线树状数组)

给你一个序列,询问一个区间内有多少个不同的数字. 经典离线树状数组,类似于HH(憨憨)的项链,把询问按照右端点排序,保证在每个数字最后一次出现的位置上加1 如果有询问的右端点等于当前加到的数字下标,就对它求一次和并累加进答案,直到所有的查询都被处理. 代码: #include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf(&quo

[bzoj1878] [SDOI2009]HH的项链(树状数组+离线)

1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3210  Solved: 1619[Submit][Status][Discuss] Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的

【树状数组】Bzoj1878[SDOI2009] HH的项链

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