您的位置:首页 > 其它

BZOJ1878: [SDOI2009]HH的项链(树状数组+离线)

2016-10-19 22:03 330 查看
Description

HH有一串由各种漂亮的贝壳组成的项链。HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义。HH不断地收集新的贝壳,因此, 他的项链变得越来越长。有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答。。。因为项链实在是太长了。于是,他只好求助睿智的你,来解 决这个问题。
Input

第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的整数)。 第三行:一个整数M,表示HH询问的个数。 接下来M行:每行两个整数,L和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
Output

M行,每行一个整数,依次表示询问对应的答案。
Sample Input
6
1 2 3 4 3 5
3
1 2
3 5
2 6
Sample Output
2
2
4
HINT
对于20%的数据,N ≤ 100,M ≤ 1000;
对于40%的数据,N ≤ 3000,M ≤ 200000;
对于100%的数据,N ≤ 50000,M ≤ 200000。


先mark一下莫队算法(不会)。
说一下我的理解吧。
这里只涉及区间查询有多少个不同值的运算,没有涉及其他修改的操作,我们可以采取离线做法。
首先呢,我们按右边界点排序(方便操作).
然后我们记录用last[i]记录某个数字最后出现的位置,pre[i]记录某个数字之前是否有出现过,没出现过则为0.
这里我们主要以某个数字的第一次出现的点代表该数字(之后无论出现多少次都以第一次出现的该数字为主).
我们从1开始算,即(1~500000,从1算到500000),这里我们只需要统计到当前所给最大的右边界就行了(1~maxR)。
[l,r]如果多次出现某个相同的数字(并且在l之前从未出现过这个数字即pre[i]=0),我们就以第一个该数字为主(肯定在l之前被统计,这就是为什么最后统计的是左边界就好了).
----扫描左端点--------------------------------------------
总结:离线做法


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 50010;
const int maxm = 200010;
using namespace std;

inline int read(){
int x(0),f(1);
char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}

int N,M;
int last[1000010],pre[1000010];
int sum[maxn],ans[maxm];
struct Sq{
int l,r,pos;
bool operator<(const Sq&t)const{
return r<t.r;
}
}sq[maxm];
inline void update(int i,int val)
{
while(i<=N){
sum[i]+=val;
i+=lowbit(i);
}
}
inline int query(int i)
{
int res=0;
while(i){
res+=sum[i];
i-=lowbit(i);
}
return res;
}

void solve()
{
int t;
N=read();
mes(last,0);
for(int i=1;i<=N;++i){
t=read();
pre[i]=last[t];
last[t]=i;
}
M=read();
for(int i=1;i<=M;++i){
sq[i].l=read(),sq[i].r=read();
sq[i].pos=i;
}
stable_sort(sq,sq+M+1);
/* for(int i=1;i<=M;++i){
cout<<sq[i].l<<" "<<sq[i].r<<endl;
}*/
int cur=0;
for(int i=1;i<=M;++i){
while(cur<sq[i].r){
++cur;
update(pre[cur]+1,1);
update(cur+1,-1);
}
ans[sq[i].pos]=query(sq[i].l);
}
for(int i=1;i<=M;++i){
printf("%d\n",ans[i]);
}
}

int main()
{
//fin;
solve();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: