【SDOI2009】【树状数组】HH的项链
来源:互联网 发布:专业数据网站 编辑:程序博客网 时间:2024/06/02 08:54
题目大意:询问一个序列中区间[a,b]中不同的数有几个,无修改操作。
比较容易想到的是使用线段树套平衡树来解决,但是这道题需要有合并的操作,时间复杂度很高,不能接受。
我们可以考虑,当一个区间有若干个同色点时,我们只能算一个,所以我们需要找出一个具有代表性的点,于是我们可以想到找区间中某种颜色第一次出现的位置来代表。并且我们可以知道这样的点的共同特点为上一个该颜色的点在查询区间的左侧,这样问题转化为求区间[a,b]中上一个同色点在[a,b]左侧的点的数目。
于是可以使用线段树套一个线性表的方法做,二分查找,在log时间内求出小区间的答案,这样就可以做到满分了。
但是我们还可以考虑更优的算法,使用离线算法,将查询区间按照右界排序,然后从前到后处理。
具体来说就是:按区间右界排序,预处理出上一个同色点的位置,然后从前到后扫描,每次将上一个同色点的值加1,将当前位置下个位置的值减1,然后求当前区间的左界的前缀和就是答案了。
这样我们需要一个可以实现两种操作的数据结构:
1、将某个位置+1或-1
2、求前缀和
而实现这两种操作的最好的数据结构就是树状数组,所以我们就用一个树状数组维护就行了。
代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 200000 + 10;const int maxm = 1000000 + 10;struct ques{int l,r;int pos;}Seg[maxn];int pre[maxn],col[maxn];int sum[maxn],ans[maxn];int last[maxm];int n,m;int cmp(const ques &a,const ques &b){return a.r < b.r;}void init(){freopen("bzoj1878.in","r",stdin);freopen("bzoj1878.out","w",stdout);}inline int lowbit(int x){return x & -x;}void add(int x,int p){while(x <= n){sum[x] += p;x += lowbit(x);}}int getsum(int x){int ret = 0;while(x > 0){ret += sum[x];x -= lowbit(x);}return ret;}void readdata(){scanf("%d",&n);for(int i = 1;i <= n;i++){scanf("%d",&col[i]);pre[i] = last[col[i]];last[col[i]] = i;}scanf("%d",&m);for(int i = 1;i <= m;i++){scanf("%d%d",&Seg[i].l,&Seg[i].r);Seg[i].pos = i;}}void solve(){stable_sort(Seg + 1,Seg + m + 1,cmp);int now = 0;for(int i = 1;i <= m;i++){while(now < Seg[i].r){++now;add(pre[now] + 1,1);if(now != n)add(now + 1,-1);}ans[Seg[i].pos] = getsum(Seg[i].l);}for(int i = 1;i <= m;i++)printf("%d\n",ans[i]);}int main(){init();readdata();solve();return 0;}
- 【SDOI2009】【树状数组】HH的项链
- 1878: [SDOI2009]HH的项链 树状数组
- 【SDOI2009】HH的项链(树状数组)
- 【bzoj1978】 [SDOI2009]HH的项链 树状数组
- BZOJ 1878 【SDOI2009】HH的项链(离线+树状数组)
- bzoj 1878 [SDOI2009]HH的项链 树状数组 离线查询
- 【COGS】421 [SDOI2009] HH的项链 树状数组
- BZOJ 1878 [SDOI2009]HH的项链 离线+树状数组
- BZOJ 1878 【SDOI2009】HH的项链(离线+树状数组)
- 洛谷1972 [SDOI2009]HH的项链(链表+树状数组)
- 【SDOI2009】【bzoj1878】HH的项链(离线+树状数组)
- 【bzoj1878】[SDOI2009]HH的项链 树状数组+离线
- bzoj 1878: [SDOI2009]HH的项链(树状数组)
- BZOJ 1878: [SDOI2009]HH的项链 树状数组+乱搞
- BZOJ1878: [SDOI2009]HH的项链(树状数组+离线)
- [SDOI2009][BZOJ1878][前缀和][树状数组]HH的项链
- BZOJ 1878: [SDOI2009]HH的项链 树状数组 离线维护
- [离线+树状数组 || 主席树]BZOJ1878: [SDOI2009]HH的项链
- Makefile 注释用法
- Linux 快速删除大量小文件方法
- 括号匹配的检验
- Python的逻辑运算
- Poems on Spring
- 【SDOI2009】【树状数组】HH的项链
- 股票指标使用 - 预测大盘
- 楼梯的走法
- 用java获取并传出虚拟机系统实时性能参数(3:socket传递参数)
- 安卓-开发常见问题之R cannot be resolved to a variable
- 信息系统项目管理师考试论文写作要点
- 将一个十进制数据转换为M进制
- mount
- MOQL--操作数(Operand) (一)