[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相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一 段贝壳,思考它们所表达的含义. ...
随机推荐
- openstack知识---hypervisor
hypervisor Hypervisor是一种运行在物理服务器和操作系统之间的中间软件层,可允许多个操作系统和应用共享一套基础物理硬件,因此也可以看作是虚拟环境中的“元”操作系统,它可以协调访问服务 ...
- 473 Matchsticks to Square 火柴拼正方形
还记得童话<卖火柴的小女孩>吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法.不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到.输入为小女孩拥有火柴的 ...
- poj2991 Crane
思路: 线段树每个节点维护第一条线段起点指向最后一条线段终点的向量,于是每一个操作都是一次区间更新.使用成段更新的线段树即可.实现: #include <cstdio> #include ...
- 短视频SDK在广电系统的解决方案
锐动视频编辑SDK集手机视频拍摄和视频剪辑主要功能于一体,同时包含手机端视频配音配乐,字幕特效,滤镜,转场特效等各种功能,全方位满足开发者的需求,并可以快速植入到APP中. 手机端的摄像头录制和直播功 ...
- sql语句中截取字符串
今天在开发过程中因为要用到合并单元格,在程序里实现了以后,查出来的数据太长,都把格式撑大了,后来想想可以在sql语句查询的时候就截取,就去网上找了一下,挺好用,就转了过来: 合并单元格: /// &l ...
- HDU_1542_(树状数组)
Stars Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- 数组,寻找第K大的数
时间复杂度 O(n) def partition(data,left,right): if (len(data)<=0 or left<0 or right>=len(data)): ...
- 配置个人Ip代理池
做爬虫最害怕的两件事一个是被封账户一个是被封IP地址,IP地址可以使用代理来解决,网上有许多做IP代理的服务,他们提供大量的IP地址,不过这些地址不一定都是全部可用,因为这些IP地址可能被其他人做爬虫 ...
- ubuntu 普通用户运行virt-manager时libvirt权限设置
error: Failed to connect socket to '/var/run/libvirt/libvirt-sock': Permission deniederror: failed t ...
- 第2节 hive基本操作:11、hive当中的分桶表以及修改表删除表数据加载数据导出等
分桶表 将数据按照指定的字段进行分成多个桶中去,说白了就是将数据按照字段进行划分,可以将数据按照字段划分到多个文件当中去 开启hive的桶表功能 set hive.enforce.bucketing= ...