P1972 [SDOI2009]HH的项链

题意:

给你一个序列,问这个序列中的种类数
n,m,ai<=1e6

题解:

三个方法:莫队(会超时),树状数组,主席树(会超时)

莫队就是裸题,不讲了,复杂度O(n*sqrt(n))

树状数组:
对于若干个区间[l,r],如果他们的r都相等,那么项链中出现的同一个数字,一定只关心最右边的那一个。
比如:1 3 4 5 1
对于r=5的所有询问,第一个位置上的1是没有价值的,因为第五个位置已经出现1,也就是对于所有查询[L,5]区间来说,如果第一个1被算,那么它完全可以用第5个1来代替
因此,我们对所有询问按照r来排序,然后维护一个树状数组。
树状数组的用途:
对于序列:1 2 1 3
我们用pre[i]来表示上一此出现i的位置
对于第一个1,insert(1,1),此时树状数组表示的每个数有1 0 0 0
对于第二个2,insert(2,1),此时1 1 0 0
对于第三个1,因为之前出现过1,所以将之前1的位置删掉,insert(1,-1),然后再把当前1加入insert(3,1).此时就是0 1 1 0
询问[2,3],就是sum(3)-sum(2-1)=2

主席树做法:
对于每个点,我们用nex表示这个点之后最近的颜色相同的点的位置,如果没有就设为n+1.
对于区间询问l~r之间的种类,其实就是求满足(l<=i<=r&&nex[i]>r)的个数,因为如果某个点的next已近超出了这个区间的范围,就说明这个点对答案产生贡献了(其实和树状数组思想是一样的,相同颜色只考虑离r最近的)
这样问题就变成在区间l~r之间权值大于r的个数
复杂度是O(mlogn),也会超时

代码:

莫队

// Problem: P1972 [SDOI2009]HH的项链
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1972
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// Data:2021-08-12 09:19:00
// By Jozky#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef ONLINE_JUDGE
#elsestartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
int n, m;
const int maxn= 3e6 + 9;
int a[maxn];
int block;
struct node
{int l, r;int id;bool operator<(const node& x) const{if (l / block != x.l / block)return l < x.l;if ((l / block) & 1)return r < x.r; // 注意这里和下面一行不能写小于(大于)等于,否则会出错(详见下面的小细节)return r > x.r;}
} q[maxn];
int ans[maxn];
int vis[maxn];
int tot= 0;
void add(int x)
{vis[a[x]]++;if (vis[a[x]] == 1)tot++;
}
void del(int x)
{vis[a[x]]--;if (vis[a[x]] == 0)tot--;
}// bool cmp(node a, node b)
// {// if (a.r / block == b.r / block)
// return a.l < b.l;
// return a.r < b.r;
// }
int main()
{//rd_test();read(n);block= sqrt(n);for (int i= 1; i <= n; i++)read(a[i]);read(m);for (int i= 1; i <= m; i++) {read(q[i].l);read(q[i].r);q[i].id= i;}sort(q + 1, q + 1 + m);int l= 1, r= 0;for (int i= 1; i <= m; i++) {int L= q[i].l, R= q[i].r;while (l < L)del(l++);while (l > L)add(--l);while (r < R)add(++r);while (r > R)del(r--);ans[q[i].id]= tot;}for (int i= 1; i <= m; i++) {printf("%d\n", ans[i]);}return 0;//Time_test();
}

树状数组

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef ONLINE_JUDGE
#elsestartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn= 2e6;
int a[maxn];
struct node
{int l, r;int id;
} q[maxn];
int sum[maxn];
int ans[maxn];
int n;
int vis[maxn];
bool cmp(node a, node b)
{return a.r < b.r;
}
int lowbit(int x)
{return x & (-x);
}
void add(int pos, int x)
{for (int i= pos; i <= n; i+= lowbit(i)) {sum[i]+= x;}
}
int query(int pos)
{int ans= 0;for (int i= pos; i >= 1; i-= lowbit(i)) {ans+= sum[i];}return ans;
}
int query(int l, int r)
{return query(r) - query(l - 1);
}
int main()
{//rd_test();read(n);for (int i= 1; i <= n; i++)read(a[i]);int m;read(m);for (int i= 1; i <= m; i++)read(q[i].l), read(q[i].r), q[i].id= i;sort(q + 1, q + 1 + m, cmp);int beg= 1;for (int i= 1; i <= m; i++) {for (int j= beg; j <= q[i].r; j++) {if (vis[a[j]])add(vis[a[j]], -1);add(j, 1);vis[a[j]]= j;}beg= q[i].r + 1;ans[q[i].id]= query(q[i].l, q[i].r);}for (int i= 1; i <= m; i++)printf("%d\n", ans[i]);return 0;//Time_test();
}

主席树

#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f;
}
template <typename T> inline void write(T x)
{if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0');
}
void rd_test()
{#ifdef ONLINE_JUDGE
#elsestartTime= clock();freopen("in.txt", "r", stdin);
#endif
}
void Time_test()
{#ifdef ONLINE_JUDGE
#elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn= 2e6 + 9;
int rs[maxn], ls[maxn];
int sum[maxn];
int n;
int a[maxn];
int rt[maxn];
int tot= 0;
int vis[maxn], nex[maxn];
void build(int& o, int l, int r)
{o= ++tot;sum[o]= 0;if (l == r)return;int mid= (l + r) >> 1;build(ls[o], l, mid);build(rs[o], mid + 1, r);
}
void update(int& o, int l, int r, int nex, int p)
{o= ++tot;ls[o]= ls[nex];rs[o]= rs[nex];sum[o]= sum[nex] + 1;if (l == r)return;int mid= (l + r) >> 1;if (p <= mid)update(ls[o], l, mid, ls[nex], p);elseupdate(rs[o], mid + 1, r, rs[nex], p);
}
int query(int u, int v, int l, int r, int k)
{int mid= (l + r) >> 1;int ans= 0;if (l == r) {return sum[v] - sum[u];}if (k <= mid) {int x= sum[rs[v]] - sum[rs[u]];ans+= query(ls[u], ls[v], l, mid, k) + x;}elseans+= query(rs[u], rs[v], mid + 1, r, k);return ans;
}
int main()
{//rd_test();read(n);for (int i= 1; i <= n; i++) {read(a[i]);if (vis[a[i]])nex[vis[a[i]]]= i;vis[a[i]]= i;}for (int i= 1; i <= n; i++) {if (!nex[i])nex[i]= n + 1;}build(rt[0], 1, n + 1);for (int i= 1; i <= n; i++) {int p= nex[i];update(rt[i], 1, n + 1, rt[i - 1], p);}int m;read(m);while (m--) {int l, r;read(l), read(r);printf("%d\n", query(rt[l - 1], rt[r], 1, n + 1, r + 1));}//Time_test();
}

P1972 [SDOI2009]HH的项链相关推荐

  1. luogu P1972 [SDOI2009] HH的项链【莫队——奇偶优化详解】

    题面 分析 莫队,往死里卡常,开O2加奇偶性优化可卡过 我才不会告诉你我这道题提交了37次呢 code // luogu-judger-enable-o2 #include<bits/stdc+ ...

  2. P1972 [SDOI2009]HH的项链(离线树状数组)

    整理的算法模板合集: ACM模板 #include<cstdio> #include<algorithm> #include<cstring> #include&l ...

  3. P1972 [SDOI2009] HH的项链

    本质上是区间查询[l,r][l,r][l,r]不重复元素的个数. 考虑离线处理,按rrr升序排序区间.假设当前区间为[l,r][l,r][l,r],我们希望查询中的query(r)−query(l−1 ...

  4. BZOJ-1878: [SDOI2009]HH的项链(莫队算法)

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 4857  Solved: 2401 [Submit][Sta ...

  5. bzoj1878: [SDOI2009]HH的项链

    树状数组的一类题目 #include<cstdio> #include<cstring> #include<iostream> #include<algori ...

  6. BZOJ 1878: [SDOI2009]HH的项链

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 3548  Solved: 1757 [Submit][Sta ...

  7. bzoj千题计划181:bzoj1878: [SDOI2009]HH的项链

    http://www.lydsy.com/JudgeOnline/problem.php?id=1878 之前用莫队做的,现在用树状数组 把每种数的第一个出现位置在树状数组中+1 nxt[i] 记录i ...

  8. BZOJ 1878: [SDOI2009]HH的项链( BIT )

    离线处理 , 记下询问的左右端点并排序 , 然后可以利用树状数组 , 保证查询区间时每种颜色只计算一次 ------------------------------------------------ ...

  9. bzoj 1878: [SDOI2009]HH的项链(主席树)

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 5317  Solved: 2624 [Submit][Sta ...

最新文章

  1. python autopy_安装python autopy时出错
  2. linux rpm目录,Linux修改RPM的安装目录的方法
  3. 目标检测之行人检测(Pedestrian Detection)基于hog(梯度方向直方图)--- 梯度直方图特征行人检测、人流检测2...
  4. 【Android 属性动画】属性动画 Property Animation 工作原理 ( 线性插值动画 | 非线性插值动画 | 动画计算 | 经过分数 | 插值分数 | 类型估值器)
  5. 引导扇区维护工具linux,BOOTICE(引导扇区维护工具)
  6. 为什么可积不一定可导_为什么一定要办理焊工证?不办会怎么样?
  7. pythonturtle库使用心得_记录我的Python学习之旅(一)关于turtle库的基本用法
  8. 分布式锁的几种实现原理
  9. Git中的pull request真正比较的是什么?
  10. 【jquery】find() 方法,filter()方法和children()方法
  11. SAP License:供应商寄售业务(合作伙伴不存在修改 443消息号)
  12. DRDS 柔性事务漫谈
  13. IMX8 Audio声卡
  14. windows服务器查看lls证书
  15. 回归模型效果评估系列3-R平方
  16. Deepin系统标题栏及其按钮美化
  17. 【电脑办公软件有哪些】万彩办公大师教程丨重复音频文件探测工具
  18. 聚焦质控 | 如何进行单病种过程质量管理
  19. 实行OBP海洋塑料认证保护海洋环境
  20. Wi-Fi无线网络下行速度超级慢 (5kb/s)之解决方案

热门文章

  1. 这几部经典纪录片,竟然还有人没看过?
  2. 就你这个求婚态度,能嫁给你才怪!
  3. 你这飞机会爆炸吗?航空公司含泪甩卖49元机票,却被超模君挖出秘密!
  4. 每天6亿人在看《延禧攻略》?大数据告诉你哪家视频网站VIP值得买(附代码)
  5. 鸿蒙思维和小央美,北市场附近艺术培训
  6. linux at java,Linux-Tutorial/Java-bin.md at master · linsanityHuang/Linux-Tutorial · GitHub
  7. 微型计算机原理中LEA,微型计算机系统原理及应用(第2版)第2章
  8. 一小时过c语言,一小时学会C语言.docx
  9. 单调谐回路谐振放大器等效电路分析_手把手教你如何分析三极管电路
  10. java虚拟机工作原理图_Java虚拟机工作原理