[HDU] (3874) Necklace ---- 离线操作+树状数组

版权声明:本文为博主原创文章,转载请预先通知博主(〃▽〃)。 https://blog.csdn.net/m0_37624640/article/details/83381254

题目传送门

几乎完全一样的题目(区间内不同数的个数): 传送门

题意: 给你n个数,q次查询,问这个区间内,区间内数的和的个数有多少种,每个不同的数只能取一次。

做法:

  • 莫队也可做,但是了解到树状数组也可以进行离线操作。
  • 思路就是,记录相同数字中上一个数字出现的位置。
    按照查询区间的右端点排序,从小到大访问右端点,更新当前位置时,如果之前有出现过相同的数字,相同数字所在的位置处更新为-a[i],否则更新为a[i]。
  • 存储答案的方式类似莫队

AC代码:

#include<bits/stdc++.h>
using namespace std;

#define IO          ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x)       push_back(x)
#define sz(x)       (int)(x).size()
#define sc(x)       scanf("%d",&x)
#define abs(x)      ((x)<0 ? -(x) : x)
#define all(x)      x.begin(),x.end()
#define mk(x,y)     make_pair(x,y)
#define fin         freopen("in.txt","r",stdin)
#define fout        freopen("out.txt","w",stdout)

typedef long long ll;
const int mod = 1e9+7;
const double PI = 4*atan(1.0);
const int maxm = 1e8+5;
const int maxn = 1e6+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 1ll<<62;

struct node
{
    int l,r;
    int id;
}q[maxn];
int n,m;
int a[maxn],pre[maxn],tmp[maxn];
ll ans[maxn],c[maxn];
inline int read()
{
    char x;
    int u,flag = 0;
    while(x = getchar(),x<'0' || x>'9') if(x == '-') flag = 1;
    u = x-'0';
    while(x = getchar(),x>='0' && x<='9') u = (u<<3)+(u<<1)+x-'0';
    if(flag) u = -u;
    return u;
}
inline int lowbit(int x){return x&(-x);}
inline void update(int x,int val)
{
    for(int i=x;i<=n;i+=lowbit(i)) c[i]+=val;
}
inline ll query(int x)
{
    ll res = 0;
    for(int i=x;i;i-=lowbit(i)) res+=c[i];
    return res;
}
inline ll range_query(int l,int r)
{
    return query(r)-query(l-1);
}
bool cmp(node a,node b){
    if(a.r == b.r) return a.l<b.l;
    else return a.r<b.r;
}
int main()
{
    // fin;
    // IO;
    int t = read();
    while(t--)
    {
        memset(tmp,0,sizeof(tmp));
        memset(c,0,sizeof(c));
        n = read();
        for(int i=1;i<=n;i++){
            a[i] = read();
            pre[i] = tmp[a[i]];
            tmp[a[i]] = i;
        }
        m = read();
        for(int i=1;i<=m;i++){
            q[i].l = read();q[i].r = read();
            q[i].id = i;
        }
        sort(q+1,q+1+m,cmp);
        int cnt = 1;
        for(int i=1;i<=m;i++)
        {
            for(;cnt<=q[i].r;cnt++)
            {
                if(pre[cnt]) update(pre[cnt],-a[cnt]);
                update(cnt,a[cnt]);
            }
            ans[q[i].id] = range_query(q[i].l,q[i].r);
        }
        for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37624640/article/details/83381254
今日推荐