• Turing Tree_线段树&树状数组


    Problem Description
    After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick thing happens again...

    Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.
     
    Input
    The first line is an integer T (1 ≤ T ≤ 10), indecating the number of testcases below.
    For each case, the input format will be like this:
    * Line 1: N (1 ≤ N ≤ 30,000).
    * Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
    * Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
    * Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).
     
    Output
    For each Query, print the sum of distinct values of the specified subsequence in one line.
     
    Sample Input
    2 3 1 1 4 2 1 2 2 3 5 1 1 2 1 3 3 1 5 2 4 3 5
     
    Sample Output
    1 5 6 3 6

    【题意】给出n个数,然后提出m个问题,求区间内不重复的数之和。

    【思路】先按查询的右坐标升序排列(保证我查询的改动不会影响到后面查询的结果)。把每个数放进线段树的时候,先判断再之前他有没有在线段树,如果在,则删除它,并把他的位置更新到当前点。

     线段树:

    #include<iostream>
    #include<stdio.h>
    #include<map>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    typedef long long int LL;
    const int N=300000+10;
    const int M=100000+10;
    int n,m;
    struct node1
    {
        int l,r;
        LL num;
    
    }sum[N*4];
    struct node
    {
        int ll,rr,index;
    
    }q[M];
    bool cmp(node x,node y)//按他的右边界排序
    {
        return x.rr<y.rr;
    }
    LL a[N];
    map<LL,int>mp;//记录是否出现过相同的数,如果有记录位置
    LL ans[M];
    void build(int k,int l,int r)//建树
    {
        sum[k].l=l;
        sum[k].r=r;
        sum[k].num=0;
        if(l==r) return ;
        int mid=l+r>>1;
        build(k*2,l,mid);
        build(k*2+1,mid+1,r);
    }
    void update(int k,int l,int r,int x,LL v)//更新结点的值
    {
        if(l==r)
        {
            sum[k].num+=v;
            return ;
        }
        int mid=l+r>>1;
        if(x<=mid) update(k*2,l,mid,x,v);
        else update(k*2+1,mid+1,r,x,v);
        sum[k].num=sum[k*2].num+sum[k*2+1].num;
    }
    LL query(int k,int l,int r,int ll,int rr)//查询区间的值
    {
       if(l>=ll&&r<=rr)
        {
            return sum[k].num;
        }
        int mid=l+r>>1;
        LL res=0;
        if(ll<=mid) res+=query(k*2,l,mid,ll,rr);
        if(rr>mid) res+=query(k*2+1,mid+1,r,ll,rr);
        return res;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            mp.clear();
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                scanf("%I64d",&a[i]);
            }
            build(1,1,n);
            scanf("%d",&m);
            for(int i=0;i<m;i++)
            {
                 scanf("%d%d",&q[i].ll,&q[i].rr);
                 q[i].index=i;
            }
            sort(q,q+m,cmp);
            int k=1;
            for(int i=0;i<m;i++)
            {
                for(;k<=q[i].rr;k++)
                {
                    if(mp[a[k]]!=0) update(1,1,n,mp[a[k]],-a[k]);//如果曾经出现过,则将以前的结点删去
                    mp[a[k]]=k;//将位置赋给当前的结点
                    update(1,1,n,k,a[k]);//将当前结点更新到树中
                }
                ans[q[i].index]=query(1,1,n,q[i].ll,q[i].rr);
            }
            for(int i=0;i<m;i++) printf("%I64d
    ",ans[i]);
        }
        return 0;
    }

    树状数组:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<map>
    #include<algorithm>
    using namespace std;
    const int N=30000+10;
    int n,m,a[N];
    long long sum[N*4],ans[N*4];
    map<int,int >mp;
    struct node
    {
        int l,r,id;
        bool operator<(const node &a)const{
            if(r==a.r) return l<a.l;
            return r<a.r;
        }
    }q[N*4];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void update(int p,int v)
    {
        while(p<=n)
        {
            sum[p]+=v;
            p+=lowbit(p);
        }
    }
    long long int  query(int p)
    {
        long long int res=0;
        while(p)
        {
            res+=sum[p];
            p-=lowbit(p);
        }
        return res;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            mp.clear();
            memset(sum,0,sizeof(sum));
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
            }
            scanf("%d",&m);
            for(int i=0;i<m;i++)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                q[i].l=l;q[i].r=r;q[i].id=i;
            }
            sort(q,q+m);
            int cnt=0;
            for(int i=1;i<=n;i++)
            {
                if(mp.find(a[i])==mp.end())//在mp中没有找到
                {
                    update(i,a[i]);
                    mp[a[i]]=i;
                }
                else
                {
                    update(i,a[i]);
                    update(mp[a[i]],-a[i]);
                    mp[a[i]]=i;
                }
                while(q[cnt].r==i)
                {
                    ans[q[cnt].id]=query(q[cnt].r)-query(q[cnt].l-1);
                    cnt++;
                }
            }
            for(int i=0;i<m;i++) printf("%lld
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    数据挖掘读书笔记-数据库系统技术
    数据挖掘读书笔记-典型的数据挖掘系统
    数据挖掘读书笔记-数据挖掘的概念
    数据产品经理做什么?
    从浏览器渲染的角度谈谈html标签的语义化
    Mozilla推动互联网成为游戏发展的强有力平台
    css知识点
    css变形 transform
    跟css背景有关的属性
    css颜色表示的方式
  • 原文地址:https://www.cnblogs.com/iwantstrong/p/6042969.html
Copyright © 2020-2023  润新知