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

Description

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

第一行:一个整数N,表示项链的长度。 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为01000000之间的整数)。 第三行:一个整数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%的数据,N100,M ≤ 1000;
对于40%的数据,N3000,M ≤ 200000;
对于100%的数据,N50000,M ≤ 200000
先mark一下莫队算法(不会)。
说一下我的理解吧。
这里只涉及区间查询有多少个不同值的运算,没有涉及其他修改的操作,我们可以采取离线做法。
首先呢,我们按右边界点排序(方便操作).
然后我们记录用last[i]记录某个数字最后出现的位置,pre[i]记录某个数字之前是否有出现过,没出现过则为0.
这里我们主要以某个数字的第一次出现的点代表该数字(之后无论出现多少次都以第一次出现的该数字为主).
我们从1开始算,即(1~500000,从1算到500000),这里我们只需要统计到当前所给最大的右边界就行了(1~maxR)。
[l,r]如果多次出现某个相同的数字(并且在l之前从未出现过这个数字即pre[i]=0),我们就以第一个该数字为主(肯定在l之前被统计,这就是为什么最后统计的是左边界就好了).
----扫描左端点--------------------------------------------
总结:离线做法
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#define Pll pair
#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
}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<
    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();
}

你可能感兴趣的:(树状数组,离线)