[luoguP1972] [SDOI2009]HH的项链(莫队 || 树状数组 || 主席树)
莫队基础题,适合我这种初学者。
莫队是离线算法,通常不带修改,时间复杂度为 O(n√n)
我们要先保证通过 [ l , r ] 求得 [ l , r + 1 ] , [ l , r - 1 ] , [ l - 1 , r ] , [ l + 1 , r ] 的效率是O(1)的
对于莫队的理解,移步远航休息栈
——代码
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm> int n, m, S, ans = ;
int a[], ton[], anslist[];
struct node
{
int l, r, id, num;
}q[]; inline int read()
{
int x = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar());
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x;
} inline bool cmp(node x, node y)
{
return x.id ^ y.id ? x.id < y.id : x.r < y.r;
} int main()
{
int i, x, y;
n = read();
for(i = ; i <= n; i++) a[i] = read();
m = read();
for(i = ; i <= m; i++) q[i].l = read(), q[i].r = read(), q[i].num = i;
S = sqrt(n);
for(i = ; i <= m; i++) q[i].id = q[i].l / S + ;
std::sort(q + , q + m + , cmp);
x = q[].l, y = q[].l;
ton[a[x]]++;
for(i = ; i <= m; i++)
{
while(x < q[i].l)
{
ton[a[x]]--;
if(!ton[a[x]]) ans--;
x++;
}
while(x > q[i].l)
{
x--;
if(!ton[a[x]]) ans++;
ton[a[x]]++;
}
while(y > q[i].r)
{
ton[a[y]]--;
if(!ton[a[y]]) ans--;
y--;
}
while(y < q[i].r)
{
y++;
if(!ton[a[y]]) ans++;
ton[a[y]]++;
}
anslist[q[i].num] = ans;
}
for(i = ; i <= m; i++) printf("%d\n", anslist[i]);
return ;
}
代码量真是友善啊
还可以用离线用树状数组来做.
以下是hzwer的解法:
这题首先在线是没法做的,所以我们可以考虑离线算法
首先记录下每种颜色的下一种颜色所在的位置
将所有询问按照左端点进行排序
将所有颜色的第一个点x a[x]++
然后从左往右扫
扫到一个点x将a[next[x]]++
碰到一个询问l,r输出sum[r]-sum[l-1]
其中sum是a数组的前缀和
求前缀和可以用树状数组
——代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> const int MAXN = ;
int n, m, max;
int head[MAXN], next[MAXN], a[MAXN], ans[MAXN], c[];
struct node
{
int l, r, id;
}q[MAXN]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int Max(int x, int y)
{
return x > y ? x : y;
} inline void update(int x)
{
for(; x <= n; x += x & -x) c[x]++;
} inline int query(int x)
{
int ret = ;
for(; x; x -= x & -x) ret += c[x];
return ret;
} inline bool cmp(node x, node y)
{
return x.l < y.l;
} int main()
{
int i, j;
n = read();
memset(head, -, sizeof(head));
for(i = ; i <= n; i++) a[i] = read(), max = Max(max, a[i]);
for(i = n; i; i--) next[i] = head[a[i]], head[a[i]] = i;
for(i = ; i <= max; i++)
if(head[i] ^ -)
update(head[i]);
m = read();
for(i = ; i <= m; i++)
{
q[i].l = read();
q[i].r = read();
q[i].id = i;
}
std::sort(q + , q + m + , cmp);
j = ;
for(i = ; i <= n; i++)
{
while(q[j].l == i) ans[q[j].id] = query(q[j].r) - query(q[j].l - ), j++;
if(next[i] ^ -) update(next[i]);
}
for(i = ; i <= m; i++) printf("%d\n", ans[i]);
return ;
}
主席树也是个好方法。
保存每个点的上一个和它颜色相同的点的位置(如果没有就是0)
然后以每个点的前驱为下标建主席数。
统计时只需要统计当前区间 [x,y] 中前驱小于 x 的点的个数
——代码
#include <cstdio>
#include <iostream> const int MAXN = ;
int n, m, cnt;
int a[MAXN], head[], pre[MAXN], root[MAXN], sum[MAXN * ], ls[MAXN * ], rs[MAXN * ]; inline int read()
{
int x = , f = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline void update(int &now, int l, int r, int x)
{
++cnt;
sum[cnt] = sum[now] + ;
ls[cnt] = ls[now];
rs[cnt] = rs[now];
now = cnt;
if(l == r) return;
int mid = (l + r) >> ;
if(x <= mid) update(ls[now], l, mid, x);
else update(rs[now], mid + , r, x);
} inline int query(int x, int y, int l, int r, int k)
{
if(l == r) return sum[y] - sum[x];
int mid = (l + r) >> ;
if(k <= mid) return query(ls[x], ls[y], l, mid, k);
else return query(rs[x], rs[y], mid + , r, k) + sum[ls[y]] - sum[ls[x]];
} int main()
{
int i, x, y;
n = read();
for(i = ; i <= n; i++)
{
a[i] = read();
pre[i] = head[a[i]];
head[a[i]] = i;
}
for(i = ; i <= n; i++)
{
root[i] = root[i - ];
update(root[i], , n, pre[i]);
}
m = read();
for(i = ; i <= m; i++)
{
x = read();
y = read();
printf("%d\n", query(root[x - ], root[y], , n, x - ));
}
return ;
}
[luoguP1972] [SDOI2009]HH的项链(莫队 || 树状数组 || 主席树)的更多相关文章
- P1972 [SDOI2009]HH的项链[离线+树状数组/主席树/分块/模拟]
题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链 ...
- zoj2112 树状数组+主席树 区间动第k大
Dynamic Rankings Time Limit: 10000MS Memory Limit: 32768KB 64bit IO Format: %lld & %llu Subm ...
- BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树
BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树 题意: 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i, ...
- 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
- 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树
题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...
- BZOJ_2120_数颜色_Set+树状数组+主席树
BZOJ_2120_数颜色_Set+树状数组+主席树 Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L ...
- P1972 [SDOI2009]HH的项链 莫队or树状数组
用什么树状数组莫队多帅 思路:树状数组\(or\)莫队(其实还是推荐树状数组\(QwQ\)) 提交:我告诉你我卡了一会儿常 卡不满原因:没有用奇偶性排序 题解: 莫队: 就是裸的莫队,把询问排序\(e ...
- Bzoj 1878: [SDOI2009]HH的项链 莫队
1878: [SDOI2009]HH的项链 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 2717 Solved: 1363[Submit][Statu ...
- BZOJ1878 [SDOI2009] HH的项链 [莫队,卡常]
BZOJ传送门,洛谷传送门 HH的项链 Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义. ...
随机推荐
- 通过Fiddler监控Java应用发送请求及相应数据
Fiddler可以很好的监控浏览器发送的各种请求及响应数据,对于JAVA程序默认情况下是无法监控的,但实际需求中需要监控JAVA程序发送HTTP请求及返回数据是否正确. Fiddler默认配置的监听端 ...
- PWA之serviceWorker应用
1.serviceWorker介绍service worker是一段运行在浏览器后台的JavaScript脚本,在页面中注册并安装成功后,它可以拦截和处理网络请求,实现缓存资源并可在离线时响应用户的请 ...
- 每天学点linux命令之locate 与 find 命令
定位某个文件的位置 方法一 sudo find / -name libGLEW.so.1.13 -type f 方法二 sudo updatedb && locate libopenc ...
- 有关LD_LIBRARY_PATH与ld.so.conf
我之前写过一篇关于LD_LIBRARY_PATH与gcc/g++ -L的关系的文章,于是我自己用CPACK制作了一个Debian安装包,然后我在/home/.bashrc里添加了export LD_L ...
- [转]C#Linq中的Union All/Union/Intersect和Top/Bottom和Paging和SqlMethods,skip,take,takewhile,skipwhile,编译查询等
本文转自:http://www.cnblogs.com/suizhikuo/p/3791799.html 我们继续讲解LINQ to SQL语句,这篇我们来讨论Union All/Union/Inte ...
- Oracle函数大全下载
Oracle函数大全下载 是一个压缩包,里面是一个chm格式的帮助文档,很实用.
- C#_JDBC连接数据库
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 归并排序算法及其JS实现
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(con ...
- SCANF输入错误
while((a<=0||a>=10)||(b<=0||b>=10)) { fflush(stdin); cout<<" ...
- Android学习笔记(十一) Intent
一.Intent对象的基本概念 -Intent是Android应用程序组件之一 -Intent对象在Android系统当中表示一种意图 -Intent当中最重要的内容是action与data 二.In ...