Turing Tree【树状数组+map优化(避免了离散化的复杂)】

刚写完了一道杭电的Necklace【HDU 3874】变深有感触,就趁热打铁做了这道图灵树(翻译过来)的题,不过这道题有个坑点就是怎么处理RE的问题?很多人——那些大佬,都是想到了用离散化来解决问题,而我不同(或许就是经常这样投机造成了我不是大佬吧),我想到的做法是用一个map去存每一个数(庆幸这题不会超memory),存的每一个数返回的是他们的地址,思路与这道题,就是Necklace做法相同,可以先做那一道在过来考虑这道题,毕竟是升华版本。

题目链接

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
struct node
{
    int l,r,id;
}q[100005];     //询问的数组,记录用
bool cmp(node e1, node e2)
{
    return e1.r<e2.r;       //按照右端升序排序,这样可以不断更新重复出现的值(先出现的更新为0)
}
int N,M;        //N:1~30000 M:1~100000
ll val[30005];      //此点的值
ll bit[200005];     //树状数组
ll pos[30005];      //这点的上一个与它值相等的点,若没有则为0
map<ll, ll>loc;      //记录目前价值的点的所在位置,便于下次找上个相同值节点的位置
ll ans[100005];      //答案记录的数组
void update(int i, ll x)    //更新
{
    while(i<=N+1)
    {
        bit[i]+=x;
        i+=lowbit(i);
    }
}
ll Query(int i)             //查找
{
    ll res=0;
    while(i)
    {
        res+=bit[i];
        i-=lowbit(i);
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(val, 0, sizeof(val));
        memset(bit, 0, sizeof(bit));
        memset(pos, 0, sizeof(pos));
        loc.clear();
        scanf("%d",&N);
        for(int i=1; i<=N; i++)
        {
            scanf("%lld",&val[i]);
            pos[i]=loc[val[i]];
            loc[val[i]]=i;
            update(i, val[i]);
        }
        scanf("%d",&M);
        for(int i=1; i<=M; i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        sort(q+1, q+1+M, cmp);
        int r=0;
        for(int i=1; i<=M; i++)
        {
            for(int j=r+1; j<=q[i].r; j++)
            {
                if(pos[j])
                {
                    update(pos[j], -val[j]);
                }
            }
            r=q[i].r;
            ans[q[i].id]=Query(q[i].r)-Query(q[i].l-1);
        }
        for(int i=1; i<=M; i++) printf("%lld\n",ans[i]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值