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

    HDU-3333 Turning Tree

    题目大意:先给出n个数字。面对q个询问区间,输出这个区间不同数的和。

    题解:这道题有几种解法。这里讲一下用分块解决的方法。( 离线树状数组解法看这里 Hdu-3333 Turning Tree (离线树状数组/线段树)~~~)

    以(a[i]上一次出现的位置last, a[i])数字对作为基本元素做分块。那么容易想到对于每一个询问(l,r),如果该元素的last<l那么这个元素就应该加入到ans中。  那么我们对于每一个分块,以last作为关键字排序。对于每一次询问。左右两端的分块就枚举last<l的a[i]加入到ans中,中间的分块因为排序的原因,last是有序的。那么中间的分块直接二分询问的左端点l,该分块左端点到二分得到的点都是符合条件的。

    AC代码如下,因为用结构体做分块的原因。代码写得稀烂~~~。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<algorithm>
    using namespace std;
    const int N=30000+10;
    const int SqrtN=200; 
    struct data{
        int last,v;
    }a[N],b[N];
    long long sum[N]; 
    int L[SqrtN],R[SqrtN];  
    int pos[N];   
    int n,m,t;
    
    bool cmp1(data x1,data x2) { return x1.last<x2.last; } 
    
    map<int,int> lst;
    void init() { 
        lst.clear();
        for (int i=1;i<=n;i++) {
            a[i].last=lst[a[i].v];
            lst[a[i].v]=i;
        }
        for (int i=1;i<=n;i++) b[i]=a[i];
    
        t=sqrt(n);
        for (int i=1;i<=t;i++) {
            L[i]=(i-1)*t+1;
            R[i]=i*t;
        }
        if (R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n;
    
    
        for (int i=1;i<=t;i++) sort(a+L[i],a+R[i]+1,cmp1);
        
        for (int i=1;i<=t;i++) {
            for (int j=L[i];j<=R[i];j++) {
                pos[j]=i;
                if (j==L[i]) sum[j]=a[j].v; else sum[j]=sum[j-1]+a[j].v;
            }
        }
    }
    
    struct cmp2
    {
        bool operator () (const data &a,const data &b) const {
            return a.last < b.last;
        }
    };
    
    long long query(int l,int r) {
        int p=pos[l],q=pos[r];
        long long ans=0;
        if (p==q) {
            for (int i=l;i<=r;i++) 
              if (b[i].last<l) ans+=b[i].v;
        } else {
            for (int i=l;i<=R[p];i++) if (b[i].last<l) ans+=b[i].v;
            for (int i=L[q];i<=r;i++) if (b[i].last<l) ans+=b[i].v;
            for (int i=p+1;i<=q-1;i++) {
                data temp;
                temp.last=l; temp.v=-1;
                int x=lower_bound(a+L[i],a+R[i]+1,temp,cmp2())-a;
                if (x!=L[i]) ans+=sum[x-1];
            }    
        }         
        return ans;
    } 
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while (T--) {
            scanf("%d",&n);
            for (int i=1;i<=n;i++) scanf("%d",&a[i].v);    
            init();
            scanf("%d",&m); 
            for (int i=1;i<=m;i++) {
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%lld
    ",query(l,r));
            }
        }
        return 0;
    } 
  • 相关阅读:
    python 循环的概念
    python 字典的基本操作
    短路表达式
    快捷键myeclipse
    nginx静态文件访问
    安装mysql
    安装mongodb
    安装tomcat
    安装jdk8
    安装node和pm2
  • 原文地址:https://www.cnblogs.com/clno1/p/9642601.html
Copyright © 2011-2022 走看看