题目链接: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 << "#\n"; 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 << "@\n"; } for (int i=0; i<n; ++i) { if (i != 0) printf(" "); printf("%d", Init[i]); } printf("\n"); for (int i=1; i<=k; ++i) { printf("%d\n", ans[i]); } } return 0; }