牛客网暑期ACM多校训练营(第一场)J-Different Integers

                                           J-Different Integers

题意很清楚啦,就是找两边区间不同数字的个数,还是自己菜啦,我一眼瞅上去感觉是莫队,主要原因是我昨天刚刚学习了qsc的莫队算法视频,以为只有查询操作,没有修改操作,用莫队就好啦,没想到T到怀疑人生,最后可能是服务器的问题吧,我莫队调整了常数,卡过去啦,不管咋说,还是要把代码贴一下,纪念自己第一个莫队算法题目(虽然还是T啦),谢谢叉姐。

代码(莫队):

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5+7;

struct node {
    ll l, r, id;
} Q[maxn];

ll n, m, k, q;
int pos[maxn];
ll a[maxn], ans[maxn], ANS = 0, cnt = 0;
int mp[maxn];

bool cmp(node a, node b)
{
    if(pos[a.l] == pos[b.l]) return a.r < b.r;
    else return pos[a.l] < pos[b.l];
}

int L = 1, R = 0;

ll rd(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void adds(int x)
{
    if(mp[a[x]] == 0) {
        ANS++;
    }
    mp[a[x]]++;
}

void del(int x)
{
    mp[a[x]]--;
    if(mp[a[x]] == 0) {
        ANS--;
    }
}

int main()
{
    while(~scanf("%lld%lld", &n, &q))
    {
        cnt = 0;
        memset(mp, 0, sizeof(mp));
        int sz = sqrt(maxn);                      //改改就过了
        for(int i = 1; i <= n; i++)
        {
            a[i] = rd();
            if(mp[a[i]] == 0) {
                mp[a[i]]++;
                cnt++;
            }
            else mp[a[i]]++;
            pos[i] = i/sz;
        }
        int cas = 0;
        for(int i = 1; i <= q; i++)
        {
            ll l, r;
            l = rd();
            r = rd();
            if(l >= (r - 1)) {
                ans[i] = cnt;
            } else {
                Q[cas].l = l;
                Q[cas].r = r;
                Q[cas++].id = i;
            }
        }

        sort(Q, Q+cas, cmp);
        ANS = cnt;
        L = Q[0].l;
        R = Q[0].l+1;
        //for(int i = L + 1; i < R; i++) del(i); ans[Q[0].id] = ANS;

        for(int i = 0; i < cas; i++)
        {
            while(L < Q[i].l)
            {
                L++;
                adds(L);
            }

            while(L > Q[i].l)
            {
                del(L);
                L--;
            }

            while(R < Q[i].r)
            {
                del(R);
                R++;
            }
            while(R > Q[i].r)
            {
                R--;
                adds(R);
            }
            ans[Q[i].id] = ANS;
        }
        //cout << "1" << endl;
        for(int i = 1; i <= q; i++) printf("%lld\n", ans[i]);
    }
    return 0;
}

题解是说用树状数组维护一下就可以啦,又学习了一下树状数组:

这里就直接借用啦题解的文字,学习好算法就好啦,解题思路也要认真学习一下,真正的学习了树状数组的维护,学习啦;

利用树状数组的维护,这样子可以在log时间复杂度内将失去的数字减去;

代码(树状数组):

#include<bits/stdc++.h>
const int maxn = 1e6+7;

using namespace std;

int n, q, cnt = 0, tot = 0;

struct Quary{
    int l, r, id;
} Q[maxn];

bool cmp(Quary a, Quary b)
{
    return a.r < b.r;
}

int main()
{
    freopen("in.txt", "r", stdin);
    while(~scanf("%d%d", &n, &q))
    {
        cnt = 0;
        tot = 0;
        vector<int> a(n+1), first(n+1, -1), last(n+1), result(q+1), count(n+1);

        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            last[a[i]] = i;
            if(first[a[i]] == -1) {
                first[a[i]] = i;
                cnt++;
            }
        }

        for(int i = 0; i < q; i++)
        {
            int l, r; scanf("%d%d", &l, &r);
            if(l>=(r-1)) result[i] = cnt;
            else {
                Q[tot].l = l;
                Q[tot].r = r;
                Q[tot++].id = i;
            }
        }

        sort(Q, Q+tot, cmp);

        for(int i = 1, k = 0; i <= n; i++)
        {
            while(k < tot&&Q[k].r == i)
            {
                int &ret = result[Q[k].id] = cnt;
                for(int j = Q[k].l; j < i; j += j&(-j)) ret -= count[j];
                k++;
            }

            if(last[a[i]] == i)
            {
                for(int j = first[a[i]] - 1; j > 0; j -= j&(-j))
                    count[j]++;
            }
        }

        for(int i = 0; i < q; i++) printf("%d\n", result[i]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39792252/article/details/81123253