zoukankan      html  css  js  c++  java
  • HDU 3333 分块求区间不同数和

    http://acm.hdu.edu.cn/showproblem.php?pid=3333

    题意:求区间不同数的和。

    思路:主席树和树状数组的的做法就不介绍了,blog里有介绍过。。这里介绍一下分块的做法(本来是想去莽5919。。。结果没莽过。。。只能改改代码拿3333来练练手了)

    这里维护每个块的值(最之前出现的位置)有序,之后就是分块套路,查询整块的时候去二分有序数组,就可以知道哪些是没有计算过的了。(显然小于L才是第一次出现)。。于是乎排序每个块之外再加一个每块的前缀和就好了。不多说看代码。。分块风格学的卿学姐的。感觉比以前自己写的清爽不少,毕竟内存不要钱嘛(误),总之很清爽233333

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAXN = 30010;
    int n,q,block,num,a[MAXN],belong[MAXN],L[MAXN],R[MAXN];
    pair<int,int> c[MAXN],d[MAXN];
    long long sum[MAXN],Q[MAXN*5];
    map<int,int> mp;
    
    int in(){
        int res=0;char c;int f=1;
        while((c=getchar())<'0' || c>'9')if(c=='-')f=-1;
        while(c>='0' && c<='9')res=res*10+c-'0',c=getchar();
        return res*f;
    }
    
    int build(int n){
        block=sqrt(n);
        num=n/block;
        if(n%block!=0) num++;
        for(int i=0;i<num;i++){
            L[i]=i*block+1;
            R[i]=(i+1)*block;
        }
        R[num-1]=n;
        int cnt=0;
        for(int i=1;i<=n;i++){
            if(i<=R[cnt]) belong[i]=cnt;
            else belong[i]=++cnt;
        }
        mp.clear();
        for(int i = 1; i<= n; i++){
            c[i]=make_pair(mp[a[i]],a[i]);
            mp[a[i]] = i;
        }
        for(int i=1;i<=n;i++) d[i]=c[i];
        for(int i=0;i<num;i++) sort(c+L[i],c+R[i]+1);
        sum[0]=0;
        for(int i=1;i<=n;i++){
            if(belong[i]==belong[i-1]) sum[i]=sum[i-1]+c[i].second;
            else sum[i]=c[i].second;
        }
    }
    
    long long query1(int l,int r){
        long long ret=0;
        if(belong[l]==belong[r]){
            for(int i=l;i<=r;i++)
                if(d[i].first<l) ret+=d[i].second;
            return ret;
        }
        for(int i=l;i<=R[belong[l]];i++)
            if(d[i].first<l) ret+=d[i].second;
        for(int i=belong[l]+1;i<belong[r];i++){
            int x=(int)(lower_bound(c+L[i],c+R[i]+1,make_pair(l,-1))-c);
            if(x!=L[i]) ret+=sum[x-1];
        }
        for(int i=L[belong[r]];i<=r;i++)
            if(d[i].first<l) ret+=d[i].second;
        return ret;
    }
    
    int main(){
        Q[0]=0;
        int t,cas=1;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            for(int i = 1; i <= n; i++) a[i]=in();
            build(n);
            scanf("%d",&q);
            int l,r;
            for(int i=1;i<=q;i++){
                l=in();r=in();
                if(r<l) swap(l,r);
                Q[i]=query1(l,r);
            }
            for(int i=1;i<=q;i++) printf("%I64d
    ",Q[i]);
        }
        return 0;
    }
    



  • 相关阅读:
    浅谈缓存管理
    [Architecture Pattern] Database Migration (上)
    knockout.js的学习笔记4
    cenOS5.5安装oracle10g(傻瓜篇)
    SportsStore:管理 — 精通ASP.NET MVC 3
    ASP.NET MVC下的异步Action的定义和执行原理
    基于EF 4.3.1 Code First的领域驱动设计实践案例
    asp.net缓存
    《Pro ASP.NET MVC 3 Framework》部署
    Asp.Net MVC 3.0【Hello World!】
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10672533.html
Copyright © 2011-2022 走看看