URAL 2080 Wallet 莫队算法

题目链接:Wallet

题意:给出n张卡片,k次使用。要求每次使用的卡片都在最上面。首先希望你合理的安排每张卡片的初始位置,并且输出。然后,问每次使用完卡片之后插入的位置上面有几张卡片,才能使得每次使用的卡片都在最上面。

思路:初始位置很容易得到。每次插入卡片时上面的卡片数,就是该卡片两次使用之间有多少个不同的数字。于是,问题变成:所有的两个相同数字之间有多少个不同的数字。

嗯..不分块会TLE的...乱用STL也会TLE的....

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <math.h>
#define maxn 100010
using namespace std;

int a[maxn];
int num[maxn];
int Ans, L, R;
int Init[maxn], cnt;
int n, k;
int los[maxn];

void getInit() {
    bool vis[maxn];
    memset(vis, 0, sizeof(vis));
    int id = 0;
    for (int i=1; i<=k; ++i) {
        if (!vis[a[i]]) {
            vis[a[i]]++;
            Init[id++] = a[i];
        }
    }
    for (int i=1; i<=n; ++i) {
        if (!vis[i]) {
            Init[id++] = i;
        }
    }
}

struct Node {
    int id;
    int l, r;
}Query[maxn];

vector<int> pos[maxn];
int ans[maxn];

void init() {
    memset(num, 0, sizeof(num));
    Ans = 1, L = 1, R = 1;
    cnt = 0;
    for (int i=0; i<=n; ++i) {
        pos[i].clear();
    }
    memset(ans, 0, sizeof(ans));
}

void getQuery() {
    for (int i=1; i<=k; ++i) {
        pos[a[i]].push_back(i);
    }
    for (int i=1; i<=n; ++i) {
        int len = pos[i].size();
        if (len == 0) continue;
        for (int j=0; j<len-1; ++j) {
            Query[cnt].l = pos[i][j];
            Query[cnt].r = pos[i][j+1];
            Query[cnt].id = pos[i][j];
            cnt++;
        }
        ans[pos[i][len-1]] = n-1;
    }
}

bool cmp(Node a, Node b) {
    if (los[a.l] != los[b.l]) return a.l < b.l;
    return a.r < b.r;
}

void Del(int x) {
    num[a[x]]--;
    if (!num[a[x]]) {
        Ans--;
    }
}

void Add(int x) {
    if (!num[a[x]]) {
        Ans++;
    }
    num[a[x]]++;
}


int main() {
    //freopen("in.cpp", "r", stdin);
    while(~scanf("%d%d", &n, &k)) {
        int kuai = (int)sqrt(k);
        for (int i=1; i<=k; ++i) {
            scanf("%d", &a[i]);
            los[i] = i/kuai;
        }
        init();
        getInit();
        num[a[1]]++;
        getQuery();
        sort(Query, Query+cnt, cmp);
        for (int i=0; i<cnt; ++i) {
            //cout << Query[i].l << " " << Query[i].r << " " << L << " " << R << "#
";
            while(Query[i].l > L) {
                Del(L);
                L++;
            }
            while(Query[i].l < L) {
                L--;
                Add(L);
            }
            while(Query[i].r > R) {
                R++;
                Add(R);
            }
            while(Query[i].r < R) {
                Del(R);
                R--;
            }
            ans[Query[i].id] = Ans-1;
            //cout << Ans << "@
";
        }
        for (int i=0; i<n; ++i) {
            if (i != 0) printf(" ");
            printf("%d", Init[i]);
        }
        printf("
");
        for (int i=1; i<=k; ++i) {
            printf("%d
", ans[i]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/icode-girl/p/5783983.html