zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    自我介绍+软工5问
    团队展示&选题
    团队展示&选题 (白衣天使队)
    结对编程(-java-实现)
    个人项目wc(Java)
    自我介绍+软工五问
    软件工程结课作业
    第四次博客作业-结对项目
    软件工程第三次作业——关于软件质量保障初探
    20194613 自动生成四则运算第一版报告
  • 原文地址:https://www.cnblogs.com/iwantstrong/p/6042969.html
Copyright © 2011-2022 走看看