zoukankan      html  css  js  c++  java
  • 【BZOJ】1878: [SDOI2009]HH的项链(树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1878

    我太弱了,看题解才过的。

    一开始看到此题,我想了想在线做法,但之后觉得这个想法可能是错的:维护一颗splay,按输入顺序建树,将相同节点缩点,维护2个值,一个是size,为节点数量,一个是size2,为不同节点数量,然后取区间操作即可。但是后来想想,此方法应该不行,因为在掉区间的时候,,你把点缩掉了。。。。。。。。。。。。。。。。。。

    写这篇文章的时候又想到一个做法。。。维护2颗splay,一颗为正常的,用来取区间,一颗为缩点的。说下做法吧,在正常的树上取了区间后,在此区间求最左边的值,用这个值放去缩点的splay上伸展到根,然后左子树的size就是答案啦~~

    来说这题的做法:

    首先我是用离线的,用树状数组维护前缀和。

    找出每个数第一次出现的位置,记为ihead[u],并且记录每个数的相同数的下一个位置,记为inext[i]。

    然后将每一个头先加入前缀后,即将所有的ihead[u]加入到前缀和中去。

    接下来将所有的询问以l排序。

    从左往右扫,如果在i这个询问前有inext,那么就全部加上去。。。。因为头已经在外面了,所以要将里面的加进去。。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define lowbit(x) (x&-x)
    #define max(a,b) ((a)>(b)?(a):(b))
    
    const int N=50005, M=200005;
    int bit[N], a[N], n, m, ihead[1000005], inext[N];
    struct Q {
    	int l, r, id, ans;
    }q[M];
    bool cmp1(const Q &a, const Q &b) { return a.l==b.l?a.r<b.r:a.l<b.l; }
    bool cmp2(const Q &a, const Q &b) { return a.id<b.id; }
    
    inline int read() {
    	int ret=0; char c;
    	for(c=getchar(); c<'0' || c>'9'; c=getchar());
    	for(; c>='0' && c<='9'; c=getchar()) ret=ret*10+c-'0';
    	return ret;
    }
    inline void add(int x, const int &y) { while(x<=n) bit[x]+=y, x+=lowbit(x); }
    inline int sum(int x) { int ret=0; while(x>0) ret+=bit[x], x-=lowbit(x); return ret; }
    
    int main() {
    	n=read();
    	int i, maxi=0, l=1;
    	for(i=1; i<=n; ++i) a[i]=read(), maxi=max(maxi, a[i]);
    	for(i=n; i>=0; --i) inext[i]=ihead[a[i]], ihead[a[i]]=i;
    	for(i=0; i<=maxi; ++i) if(ihead[i]) add(ihead[i], 1);
    	m=read();
    	for(i=1; i<=m; ++i) q[i].l=read(), q[i].r=read(), q[i].id=i;
    	sort(q+1, q+1+m, cmp1);
    	for(i=1; i<=m; ++i) {
    		while(l<q[i].l) {
    			if(inext[l]) add(inext[l], 1);
    			++l;
    		}
    		q[i].ans=sum(q[i].r)-sum(q[i].l-1);
    	}
    	sort(q+1, q+1+m, cmp2);
    	for(i=1; i<=m; ++i) printf("%d
    ", q[i].ans);
    	return 0;
    }
    

    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。

    Source

  • 相关阅读:
    mavenjar 一些拉取不下来问题
    storm运行服务器一些错误解决、
    python操作excel库xlwings---3、写入excel常见操作
    python操作excel库xlwings---2、写入excel基本操作
    python操作excel库xlwings---1、课程介绍
    numpy库常用基本操作
    Numpy库使用总结
    python的xlwings库读写excel操作总结
    numpy中的ndarray与pandas的Series和DataFrame之间的相互转换
    Numpy和Pandas的区别
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3874258.html
Copyright © 2011-2022 走看看