SPOJ 3267 D-query(离散化+在线主席树 | 离线树状数组)
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(离散化+在线主席树 | 离线树状数组)的更多相关文章
- SPOJ 3267 D-query(离散化+主席树求区间内不同数的个数)
DQUERY - D-query #sorting #tree English Vietnamese Given a sequence of n numbers a1, a2, ..., an and ...
- SPOJ DQUERY D-query (在线主席树/ 离线树状数组)
版权声明:本文为博主原创文章,未经博主允许不得转载. SPOJ DQUERY 题意: 给出一串数,询问[L,R]区间中有多少个不同的数 . 解法: 关键是查询到某个右端点时,使其左边出现过的数都记录在 ...
- hdu 4605 Magic Ball Game (在线主席树/离线树状数组)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球 ...
- 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 ...
- HDU 5869 Different GCD Subarray Query rmq+离线+数状数组
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5869 Different GCD Subarray Query Time Limit: 6000/3 ...
- bzoj 2434: 阿狸的打字机 fail树+离线树状数组
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...
- 【SPOJ QTREE4】Query on a tree IV(树链剖分)
Description 给出一棵边带权(\(c\))的节点数量为 \(n\) 的树,初始树上所有节点都是白色.有两种操作: C x,改变节点 \(x\) 的颜色,即白变黑,黑变白. A,询问树中最远的 ...
- 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 # ...
- BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P ...
随机推荐
- python_99_面向对象多态
#多态:一种接口,多种实现.主要作用:实现接口重用 #方法1: class Animal(object): def __init__(self,name): self.name=name class ...
- ASP.NET 验证控件报错:WebForms UnobtrusiveValidationMode 需要“jquery”ScriptResourceMapping。
在Visual Studio 2012中添加并使用验证控件时,可能会遇到如下的错误: WebForms UnobtrusiveValidationMode 需要“jquery”ScriptResour ...
- mutt+msmtp做linux邮件客户端
mutt+msmtp做linux邮件客户端 1. 安装配置msmtp l 安装 wget https://sourceforge.net/projects/msmtp/files/msmtp/1.4 ...
- cocos2dx for lua 简单的翻牌动画
local x = 20 local y = display.height/2 for i = 1,16 do--创建16张 local cardFg = display.newSprite(&quo ...
- C++ 学习笔记(三)string 类
在C语言中如果想要使用字符串那么有两种方法: 1.定义char型数组:char[10]; 然后将每个字符填充到对应的位置. 优点:这种方式将字符串放在内存所以每个位置都可以修改. 缺点:赋值比较麻烦, ...
- 概括的描述一下Spring注册流程
Spring经过大神们的构思.编码,日积月累而来,所以,对其代码的理解也不是一朝一夕就能快速完成的.源码学习是枯燥的,需要坚持!坚持!坚持!当然也需要技巧,第一遍学习的时候,不用关注全部细节,不重要的 ...
- CentOs 6.5设置使用私钥登录关闭ssh的密码登录修改ssh默认端口
使用SecureCRT工具创建RSA公钥和私钥 [选项]=>[会话选项] 然后在弹出对话框中选择[公钥]然后点击[属性]: 在弹出窗口中选中[使用会话公钥设置],点击[创建身份文件]按钮: 然后 ...
- 【前端_js】Json对象和Json字符串的区别
转载1: Json对象和Json字符串的区别 转载2: JSON字符串与JSON对象的区别
- MYSQL不能显示中文字,显示错误“ERROR 1366 (HY000): Incorrect string value: '\xE5\xBC\xA0\xE4\xB8\x89'”
或者建表时带上编码utf8 CREATE TABLE `students`( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR( ...
- Python爬虫系列-PyQuery详解
强大又灵活的网页解析库.如果你觉得正则写起来太麻烦,如果你觉得BeautifulSoup语法太难记,如果你熟悉jQuery的语法,那么PyQuery就是你的最佳选择. 安装 pip3 install ...