• HDU 3333 Turing Tree 题解(线段树+离线操作)


    题目链接

    题目大意

    给你一个长度为(n(nle30000))的数组(a)

    给你(m(mle100000))次查询,求出区间([l,r])中出现过的数字之和(出现过多次只算一次)

    题目思路

    这个乍一看很像线段树,其实也是线段树

    但是你会发现你根本不好去维护这个线段树

    你发现没这个数组没有修改操作,都是查询操作

    那么对于这种题目就应该要想到离线操作

    把所有查询按照(r)升序排序

    然后保证([1,r])中若出现相同的数,则这个数只在([1,r])的最右边记录

    那么这样显然可以保证答案的正确性,只要有一个(last)数组维护每个元素前的相同元素的最近值即可

    由于(a[i])达到(10^9)(map)即可

    代码

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define debug cout<<"I AM HERE"<<endl;
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
    const double eps=1e-6;
    int n,m;
    int a[maxn];
    ll ans[maxn];
    ll tree[maxn<<2];
    struct node{
        int l,r,id;
    }nd[maxn];
    bool cmp(node a,node b){
        return a.r<b.r;
    }
    ll query(int node,int l,int r,int ql,int qr){
        //这里没有被建树,显然没有值
        if(ql<=l&&r<=qr){
            return tree[node];
        }
        int mid=(l+r)/2;
        ll sum=0;
        if(mid>=ql) sum+=query(node<<1,l,mid,ql,qr);
        if(mid<qr) sum+=query(node<<1|1,mid+1,r,ql,qr);
        return sum;
    }
    void update(int node,int l,int r,int pos,int val){
        if(l==r){
            tree[node]=val;
            return ;
        }
        int mid=(l+r)/2;
        if(mid>=pos)    update(node<<1,l,mid,pos,val);
        else    update(node<<1|1,mid+1,r,pos,val);
        tree[node]=tree[node<<1]+tree[node<<1|1];
    }
    signed main(){
        int _;scanf("%d",&_);
        while(_--){
            map<int,int>last;
            memset(tree,0,sizeof(tree));
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            scanf("%d",&m);
            for(int i=1;i<=m;i++){
                scanf("%d%d",&nd[i].l,&nd[i].r);
                nd[i].id=i;
            }
            sort(nd+1,nd+1+m,cmp);
            int pos=1;
            for(int i=1;i<=m;i++){
                while(pos<=nd[i].r){
                    if(last[a[pos]]){
                        update(1,1,n,last[a[pos]],0);
                    }
                    update(1,1,n,pos,a[pos]);
                    last[a[pos]]=pos;
                    pos++;
                }
                ans[nd[i].id]=query(1,1,n,nd[i].l,nd[i].r);
            }
            for(int i=1;i<=m;i++){
                printf("%lld
    ",ans[i]);
            }
        }
        return 0;
    }
    
    
    
    卷也卷不过,躺又躺不平
  • 相关阅读:
    STL 源代码分析 算法 stl_algo.h -- includes
    Objective-c 算术函数和常量代表
    文件比较,文件夹比较-- vimdiff,beyond compare, compare suite, WinMerge,Kdiff3
    PHP+lghttpd + postgresql 环境搭建
    开源免费跨平台opengl opencv webgl gtk blender, opengl贴图程序
    expect 参数处理之一
    几款屏幕录制软件 ActivePresente
    gcc -D 传值给代码,默认值为1
    error: /usr/include/stdio.h: Permission denied 的一种情况分析
    linux内核编译环境配置
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14641048.html
Copyright © 2020-2023  润新知