题意:有n个影碟,标号为1~n,位置为0~n-1,每次取出一个影碟看完后,将其放在最前面(标号为0处),问每个影碟取出前,其位置之前有多少个影碟。
分析:
1、数组大小开为100000*2,后100000个位置放初始的n个影碟,每次看完一个影碟后,依次向前放在前100000个位置中。
2、将放置影碟处标记为1---add(x, 1),当影碟取出时,再add(x,-1)。
3、通过sum(x)-1可知当前位置之前有多少个影碟。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cctype> #include<cmath> #include<iostream> #include<sstream> #include<iterator> #include<algorithm> #include<string> #include<vector> #include<set> #include<map> #include<stack> #include<deque> #include<queue> #include<list> #define lowbit(x) (x & (-x)) const double eps = 1e-8; inline int dcmp(double a, double b){ if(fabs(a - b) < eps) return 0; return a > b ? 1 : -1; } typedef long long LL; typedef unsigned long long ULL; const int INT_INF = 0x3f3f3f3f; const int INT_M_INF = 0x7f7f7f7f; const LL LL_INF = 0x3f3f3f3f3f3f3f3f; const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f; const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1}; const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; const int MOD = 1000; const double pi = acos(-1.0); const int MAXN = 200000 + 10; const int MAXT = 10000 + 10; using namespace std; int a[MAXN]; int n, m; int pos[MAXN]; int sum(int x){ int ans = 0; for(int i = x; i >= 1; i -= lowbit(i)){ ans += a[i]; } return ans; } void add(int x, int value){ for(int i = x; i < MAXN; i += lowbit(i)){ a[i] += value; } } vector<int> ans; int main(){ int T; scanf("%d", &T); while(T--){ ans.clear(); memset(a, 0, sizeof a); scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i){ pos[i] = 100000 + i; add(pos[i], 1); } int cnt = 100000; while(m--){ int k; scanf("%d", &k); ans.push_back(sum(pos[k]) - 1); add(pos[k], -1); pos[k] = cnt--; add(pos[k], 1); } int len = ans.size(); for(int i = 0; i < len; ++i){ if(i) printf(" "); printf("%d", ans[i]); } printf(" "); } return 0; }