zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    【XAF】非持久化对象分组和属于不同会话
    【原创】XAF 非持久对象界面中更新xpo的状态查询
    Java字符串操作方法集
    Java易忘知识点统计
    Android常用依赖库搜集
    Android Studio报错Unable to resolve dependency for ':app@release/compileClasspath':无法引用任何外部依赖的解决办法
    Codewars练习Python
    Python学习日记之正则表达式re模块
    Linux学习日记之crontab使用notify-send实现每小时通知提醒
    Linux学习日记之Deepin下查看crontab运行日志
  • 原文地址:https://www.cnblogs.com/icode-girl/p/5783983.html
Copyright © 2011-2022 走看看