给出q个询问,询问一段区间里面的不同元素的个数有多少个。

离线做,用树状数组。

设树状数组的意义是:1--pos这个段区间的不用元素的种类数。怎么做?就是add(pos,1);在这个位置中+1,就是说这个位置上元素种类+1。

然后先把询问按R递增的顺序排序。因为这里是最优的,我每次尽量往R靠,使得查询不重不漏。

什么意思呢?

就是假如有:2、1、3、5、1、7的话。

一开始的[1,4]这段数字全部压进树状数组,用个数组book[val],表示val这个元素出现的最右的位置,因为我们需要删除重复的,也是要尽量往右靠。到达pos=5这个位置的时候,注意了,因为1是出现过的book[1] = 2,所以我们要做的是把2这个位置出现元素的种类数-1,就是add(book[1],-1)。然后把第五个位置出现的元素种类数+1,就是add(5,1)。为什么呢?因为你尽量把种类往右靠,因为我们的R是递增的,这样,你使得查询[4,6]成为可能,因为我那个1加入来了,而不是一直用pos=2那个位置的1,再者,查询[4,7]的话,一样的意思,因为中间的1进来了。所以我们因为尽量往右靠,毕竟我们都把query按R排序了。

还有这个只能离线,一直预处理ans[i]表示第i个询问的ans。更新到[4,7]后,查询[1,2]已经不可能了,因为很明显,pos=2这个位置已经被删除了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 1e6+;
int book[maxn];
int c[maxn];//树状数组,多case的记得要清空
int n; //我只需记录这个位置是不是新元素,不用离散
int lowbit (int x)//得到x二进制末尾0的个数的2次方 2^num
{
return x&(-x);
}
void add (int pos,int val)//在第pos位加上val这个值
{
while (pos<=n) //n是元素的个数
{
c[pos] += val; pos += lowbit(pos);
}
return ;
}
int get_sum (int pos) //求解:1--pos的总和
{
int ans = ;
while (pos)
{
ans += c[pos]; pos -= lowbit(pos);
}
return ans;
}
int a[maxn];
struct node
{
int L,R,id;
bool operator < (const struct node &rhs) const
{
if (R != rhs.R) return R < rhs.R;
else return L < rhs.L;
}
}query[maxn];
int ans[maxn];
void work ()
{
scanf("%d",&n);
for (int i=;i<=n;++i) scanf("%d",&a[i]);
//树状数组含义:1--pos间的不同元素种类数
int q; scanf("%d",&q);
for (int i=;i<=q;++i)
{
scanf("%d%d",&query[i].L,&query[i].R);
query[i].id = i; //记录ans
}
sort(query+,query++q);
int cur = ;
//book[val]的含义,val这个元素出现的最右边的位置
for (int i=;i<=q;++i)
{
for (int j=cur;j<=query[i].R;++j)
{
if (book[a[j]]) //这个元素在之前位置出现过,我们尽量往右,所以先删除那个位置的种类数,更新现在这个位置的种类数。因为这样的话,使得查询[4,5]是可能的
add(book[a[j]],-); //del 这个位置
book[a[j]]=j; //更新这个位置的最右值
add(j,); //这个位置出现了新元素
}
cur = query[i].R+;
ans[query[i].id] = get_sum(query[i].R) - get_sum(query[i].L-);
}
for (int i=;i<=q;++i)
printf ("%d\n",ans[i]);
} int main()
{
#ifdef local
freopen("data.txt","r",stdin);
#endif
work();
return ;
}

HDU 3333 Turing Tree

一样的,只不过是求元素的和。。把add那里的val改成a[i]即可,幻想它出现了val次,一统计,就是了。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
LL c[maxn];//树状数组,多case的记得要清空
int n;
LL a[maxn];
struct node
{
int L,R,id;
bool operator < (const struct node &rhs) const
{
return R < rhs.R;
}
}query[*];
LL ans[*];
map<LL,int>book;
int lowbit (int x)//得到x二进制末尾0的个数的2次方 2^num
{
return x&(-x);
}
void add (int pos,LL val)//在第pos位加上val这个值
{
while (pos<=n) //n是元素的个数
{
c[pos] += val; pos += lowbit(pos);
}
return ;
}
LL get_sum (int pos) //求解:1--pos的总和
{
LL ans = ;
while (pos)
{
ans += c[pos]; pos -= lowbit(pos);
}
return ans;
}
void init ()
{
memset(c,,sizeof c);
book.clear();
return ;
}
void work ()
{
init();
scanf("%d",&n);
for (int i=;i<=n;++i) scanf("%I64d",&a[i]);
int q;
scanf ("%d",&q);
for (int i=;i<=q;++i)
{
scanf("%d%d",&query[i].L,&query[i].R);
query[i].id = i;
}
sort(query+,query++q);
int cur=;
for (int i=;i<=q;++i)
{
for (int j=cur;j<=query[i].R;++j)
{
int t = book[a[j]];
if (t)
{
add(t,-a[j]);
}
book[a[j]]=j;
add(j,a[j]);
}
cur = query[i].R+;
ans[query[i].id] = get_sum(query[i].R) - get_sum(query[i].L-);
}
for (int i=;i<=q;++i)
{
printf ("%I64d\n",ans[i]);
}
} int main()
{
#ifdef local
freopen("data.txt","r",stdin);
#endif
int t;
scanf ("%d",&t);
while (t--) work();
return ;
}

SPOJ 3267: DQUERY 树状数组,离线算法的更多相关文章

  1. SPOJ DQUERY树状数组离线or主席树

    D-query Time Limit: 227MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Submit Status ...

  2. D-query SPOJ 树状数组+离线

    D-query SPOJ 树状数组+离线/莫队算法 题意 有一串正数,求一定区间中有多少个不同的数 解题思路--树状数组 说明一下,树状数组开始全部是零. 首先,我们存下所有需要查询的区间,然后根据右 ...

  3. 2016 Multi-University Training Contest 5 1012 World is Exploding 树状数组+离线化

    http://acm.hdu.edu.cn/showproblem.php?pid=5792 1012 World is Exploding 题意:选四个数,满足a<b and A[a]< ...

  4. Necklace HDU - 3874 (线段树/树状数组 + 离线处理)

    Necklace HDU - 3874  Mery has a beautiful necklace. The necklace is made up of N magic balls. Each b ...

  5. HDU 4417 - Super Mario ( 划分树+二分 / 树状数组+离线处理+离散化)

    题意:给一个数组,每次询问输出在区间[L,R]之间小于H的数字的个数. 此题可以使用划分树在线解决. 划分树可以快速查询区间第K小个数字.逆向思考,判断小于H的最大的一个数字是区间第几小数,即是答案. ...

  6. BZOJ1878: [SDOI2009]HH的项链[树状数组 离线]

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 3486  Solved: 1738[Submit][Statu ...

  7. HDU3333 Turing Tree 树状数组+离线处理

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  8. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  9. Codeforces Round #365 (Div. 2) D 树状数组+离线处理

    D. Mishka and Interesting sum time limit per test 3.5 seconds memory limit per test 256 megabytes in ...

随机推荐

  1. TFS自定义开发中的反射应用

    最近CM(Configuration Management) 的同事在自定义开发TFS的过程中遇到一个问题. 领导要求快速开发一个工具, 可以自动连接TFS,然后自动Check out一些word文件 ...

  2. fiddler 的AutoRespoder的使用(手动添加测试桩)

    ---恢复内容开始--- 1.首先我们抓取一个百度的请求,由于百度请求是https协议,需要手动添加证书(这个不写了,大佬们自己手动找下资料) 2.fiddler抓取的百度请求,其他的无关信息删除,便 ...

  3. 杂项:Webpack

    ylbtech-杂项:Webpack 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地 ...

  4. delphi 线程教学第一节:初识多线程

    第一节:初识多线程   1.为什么要学习多线程编程?   多线程(多个线程同时运行)编程,亦可称之为异步编程. 有了多线程,主界面才不会因为耗时代码而造成“假死“状态. 有了多线程,才能使多个任务同时 ...

  5. day18-事务与连接池 4.事务特性

  6. Entity Framework Code-First(9.11):DataAnnotations - InverseProperty Attribute

    DataAnnotations - InverseProperty Attribute: We have seen in the Code-First Convention section that ...

  7. UITableViewCell 的复用机制

    cell重用机制 http://blog.cnrainbird.com/index.php/2012/03/20/guan_yu_uitableview_de_cell_fu_yong_tan_tan ...

  8. 浅析C#中的事件

    讲过了委托,不得不讲事件. 事件基于委托,为委托提供了一种发布/订阅机制. 在发生其他类或对象关注的事情时,类或对象可通过事件通知它们.发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为 ...

  9. Ansible Playbooks基本使用

    你将学到什么 如何使用playbook 如何编写playbook 如何使用roles PlayBook使用 基础环境 ### 64 位 Ubuntu 16.04 LTS,创建CentOS LXC容器w ...

  10. Python包管理工具setuptools之setup函数参数详解

    **********************************************************对所学内容的简单汇总******************************** ...