DQUERY - D-query

English Vietnamese

Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, ..., aj.

Input

  • Line 1: n (1 ≤ n ≤ 30000).
  • Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
  • Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
  • In the next q lines, each line contains 2 numbers i, j representing a d-query (1 ≤ i ≤ j ≤ n).

Output

  • For each d-query (i, j), print the number of distinct elements in the subsequence ai, ai+1, ..., aj in a single line.

Example

Input
5
1 1 2 1 3
3
1 5
2 4
3 5 Output
3
2
3

题目链接:SPOJ 3267

假设数组从1开始,以当前数字的位置(下标)为pos,贡献为1,用主席树维护前缀序列[1,i]的贡献和,则显然第i棵线段树就是对应的前缀序列[1,i],

有两种情况,这个数字之前出现过,比如6 6 6 2 3,扫到第二个1的时候发现lastpos中6的位置为1,则先把上一次的树拿来作一次更新,更新所得到的根储存在temp里,再把temp作为上一次的依存根,以root[i]现在的根进行更新,即重新定位了6的位置,总体来说就是每一次把出现过的数字位置都维护成最新的再配合主席树

题目给出l与r,r可直接用,显然l还不对需要转换,我这里写的和其他人的做法不太一样,还是用区间内的区间求和思想。即对root[l-1]~root[r]求l~r的区间和。因为用的是下标而不是原值更不是离散化之后的值作插入位置,因此l,r既是询问区间也是求和区间。一开始范围搞错了把离散化之后的size作为值域大小,wa数次……,此外这题似乎还可以莫队或者离线树状数组搞搞,前者太模版了懒的写,后者理解不够深入就先不贴代码了,最近学了下离线树状数组,发现可以搞的1A过了,而且时间比主席树快

主席树代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
typedef pair<int,int> pii;
typedef long long LL;
const double PI=acos(-1.0);
const int N=30010;
struct seg
{
int lson,rson;
int cnt;
};
seg T[N*20];
int root[N],tot;
vector<int>pos;
int arr[N];
int last_pos[N]; void init()
{
pos.clear();
CLR(root,0);
tot=0;
T[0].cnt=T[0].lson=T[0].rson=0;
CLR(last_pos,0);
}
void update(int &cur,int ori,int l,int r,int pos,int flag)
{
cur=++tot;
T[cur]=T[ori];
T[cur].cnt+=flag;
if(l==r)
return ;
int mid=MID(l,r);
if(pos<=mid)
update(T[cur].lson,T[ori].lson,l,mid,pos,flag);
else
update(T[cur].rson,T[ori].rson,mid+1,r,pos,flag);
}
int query(int S,int E,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
return T[E].cnt-T[S].cnt;
else
{
int mid=MID(l,r);
if(y<=mid)
return query(T[S].lson,T[E].lson,l,mid,x,y);
else if(x>mid)
return query(T[S].rson,T[E].rson,mid+1,r,x,y);
else
return query(T[S].lson,T[E].lson,l,mid,x,mid)+query(T[S].rson,T[E].rson,mid+1,r,mid+1,y);
}
}
int main(void)
{
int n,m,i,l,r;
while (~scanf("%d",&n))
{
init();
for (i=1; i<=n; ++i)
{
scanf("%d",&arr[i]);
pos.push_back(arr[i]);
}
scanf("%d",&m);
sort(pos.begin(),pos.end());
pos.erase(unique(pos.begin(),pos.end()),pos.end());
int temp_rt=0;
for (i=1; i<=n; ++i)
{
arr[i]=lower_bound(pos.begin(),pos.end(),arr[i])-pos.begin()+1;
if(!last_pos[arr[i]])
{
update(root[i],root[i-1],1,n,i,1);
last_pos[arr[i]]=i;
}
else
{
update(temp_rt,root[i-1],1,n,last_pos[arr[i]],-1);
update(root[i],temp_rt,1,n,i,1);
last_pos[arr[i]]=i;
}
}
for (i=0; i<m; ++i)
{
scanf("%d%d",&l,&r);
printf("%d\n",query(root[l-1],root[r],1,n,l,r));
}
}
return 0;
}

离线树状数组代码:

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 30010;
const int M = 200010;
struct info
{
int k, l, r, flag, id;
info() {}
info(int _k, int _l, int _r, int _flag, int _id): k(_k), l(_l), r(_r), flag(_flag), id(_id) {}
bool operator<(const info &rhs)const
{
return k < rhs.k;
}
};
info Q[M << 1];
int T[N], ans[M];
int arr[N], last[N];
vector<int>xpos; void init()
{
CLR(T, 0);
CLR(ans, 0);
CLR(last, 0);
xpos.clear();
}
void add(int k, int v)
{
while (k < N)
{
T[k] += v;
k += (k & -k);
}
}
int getsum(int k)
{
int ret = 0;
while (k)
{
ret += T[k];
k -= (k & -k);
}
return ret;
}
int main(void)
{
int n, m, i;
while (~scanf("%d", &n))
{
init();
for (i = 1; i <= n; ++i)
{
scanf("%d", &arr[i]);
xpos.push_back(arr[i]);
}
sort(xpos.begin(), xpos.end());
xpos.erase(unique(xpos.begin(), xpos.end()), xpos.end());
for (i = 1; i <= n; ++i)
arr[i] = lower_bound(xpos.begin(), xpos.end(), arr[i]) - xpos.begin() + 1;
scanf("%d", &m);
int qcnt = 0;
for (i = 0; i < m; ++i)
{
int l, r;
scanf("%d%d", &l, &r);
Q[qcnt++] = info(l, l, r, 0, i);
Q[qcnt++] = info(r, l, r, 1, i);
}
sort(Q, Q + qcnt);
int x = 1;
for (i = 0; i < qcnt; ++i)
{
while (x <= Q[i].k)
{
int val = arr[x];
if (!last[val])
add(x, 1);
else
{
add(last[val], -1);
add(x, 1);
}
last[val] = x;
++x;
}
if (Q[i].flag)
ans[Q[i].id] += getsum(Q[i].r) - getsum(Q[i].l - 1);
else//实际上这里可以再优化,在l-1之外的求和肯定为0,这里可以不需要的
{
add(last[arr[x - 1]], -1);
ans[Q[i].id] -= getsum(Q[i].r) - getsum(Q[i].l - 1);
add(last[arr[x - 1]], 1);
}
}
for (i = 0; i < m; ++i)
printf("%d\n", ans[i]);
}
return 0;
}

SPOJ 3267 D-query(离散化+在线主席树 | 离线树状数组)的更多相关文章

  1. SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)

    DQUERY - D-query #sorting #tree English Vietnamese Given a sequence of n numbers a1, a2, ..., an and ...

  2. SPOJ DQUERY D-query (在线主席树/ 离线树状数组)

    版权声明:本文为博主原创文章,未经博主允许不得转载. SPOJ DQUERY 题意: 给出一串数,询问[L,R]区间中有多少个不同的数 . 解法: 关键是查询到某个右端点时,使其左边出现过的数都记录在 ...

  3. hdu 4605 Magic Ball Game (在线主席树/离线树状数组)

    版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球 ...

  4. SPOJ DQUERY - D-query (莫队算法|主席树|离线树状数组)

    DQUERY - D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query ...

  5. HDU 5869 Different GCD Subarray Query rmq+离线+数状数组

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5869 Different GCD Subarray Query Time Limit: 6000/3 ...

  6. bzoj 2434: 阿狸的打字机 fail树+离线树状数组

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...

  7. 【SPOJ QTREE4】Query on a tree IV(树链剖分)

    Description 给出一棵边带权(\(c\))的节点数量为 \(n\) 的树,初始树上所有节点都是白色.有两种操作: C x,改变节点 \(x\) 的颜色,即白变黑,黑变白. A,询问树中最远的 ...

  8. Codeforces Round #345 (Div. 1) D - Zip-line 带单点修改的LIS 主席树 | 离线树状数组

    D - Zip-line #include<bits/stdc++.h> #define LL long long #define fi first #define se second # ...

  9. BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)

    墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P ...

随机推荐

  1. python_81_标准库_时间模块

    ''' 标准库: 1.time 时间的三种表示方法:a:时间戳(timestamp) b:格式化的时间字符串 c:元组(struct_time)共九个元素 time.struct_time(tm_ye ...

  2. 【Python全栈-JavaScript】JavaScript-字符串详解

    JavaScript-字符串详解 预热:Number() 方法 <script> //重要等级 1,2,3,4,5 var s=10; //最高级别5 var s1=new Number( ...

  3. 解决Error"基础连接已经关闭: 未能为SSL/TLS 安全通道建立信任关系

    今天写程序的时候调用到一个第三方的DLL文件,本机调试一切都正常,但是程序不是到服务器以后一直提示一个BUG:"基础连接已经关闭: 未能为SSL/TLS 安全通道建立信任关系".  ...

  4. Bootstrap历练实例:默认的面板(Panels)

    Bootstrap 面板(Panels) 本章将讲解 Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素 ...

  5. Java第7次作业:造人类(用private封装,用static关键字自己造重载输出方法)什么是面向对象程序设计?什么是类和对象?什么是无参有参构造方法 ?什么是封装?

    什么是面向对象程序设计? 我们称为OOP(Object  Oriented  Programming) 就是非结构化的程序设计 要使用类和对象的方法来进行编程 什么是类,什么是对象 类就是封装了属性和 ...

  6. cocos2dx 使用XMLHttpRequest时回调status为0的问题

    今天使用cocos连接http访问时,使用XMLHttpRequest在pc上反问时正常的返回了status=0,但是在android上去返回status是0,看了一下底层代码, 发现status只有 ...

  7. redis的一个bug

    清楚redis缓存的时候,出现以下问题: (error) MISCONF Redis is configured to save RDB snapshots, but is currently not ...

  8. 变量赋值理解--Pyton中让两个值互换的方法

    #Pyton中让两个值互换的方法 #方法一:可以理解为相当于是同时赋值 a = 5 b = 4 a,b = b,a print(a,b) #方法二:可以理解为拿箱子过程 c = 10 d = 20 e ...

  9. NordicSemiconductor.nRF_DeviceFamilyPack 更新历史记录

    Version: 8.17.0 (2018-04-27) NordicSemiconductor.nRF_DeviceFamilyPack.8.17.0.packDownload For nRF528 ...

  10. CodeForces - 485D Maximum Value (数学)

    题意: n个数,求出这些数中满足 ai >= aj 的 ai % aj 的最大值. 排序去重,然后对于每一个a[i], 如果找到a[i] 的一个倍数 k*a[i] (k > 1)的位置,那 ...