用树状数组动态和查询修改排名。
树状数组可以很方便地查询前缀和,那么可以利用这一特点,记录一个点在树状数组里最后一次出现的位置,
查询出这个位置,就可以知道这个点的排名了。更改这个点的排名的时候只要把原来位置修改成0,然后在新的位置加上1就行了。
把询问离线,数据范围比较大,先用快排+去重离散(用map也可,就是慢了一点),
很久以前看的了,今天第一次实现
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5, N = maxn*2-1; int a[maxn],q[maxn],C[N+1],sz,pos[maxn]; #define lowbit(x) ((x)&-(x)) void add(int x,int d) { while(x<N){ C[x] += d; x += lowbit(x); } } int sum(int x) { int ret = 0; while(x>0){ ret += C[x]; x -= lowbit(x); } return ret; } int b_search(int val,int *A = a,int l = 0,int r = sz) { int m; while(l<r){ m = (l+r)>>1; if(val>A[m]) l = m+1; else if(val<A[m]) r = m; else return m; } return -1; } int main() { freopen("mtf.in","r",stdin); freopen("mtf.out","w",stdout); int n; cin>>n; for(int i = 0; i < n; i++) scanf("%d",a+i),q[i]=a[i]; sort(a,a+n); sz = unique(a,a+n)-a; for(int i = 0; i < sz; i++){ add(pos[i] = maxn+i,1); } int cur = maxn-1; for(int i = 0; i < n; i++){ int x = b_search(q[i]), ans; //cout<<x<<endl; if(pos[x] == maxn+x) ans = sum(pos[x]) - x-1 + q[i]; else ans = sum(pos[x]); printf("%d%c",ans,i==n-1?‘\n‘:‘ ‘); add(pos[x],-1); add(pos[x] = cur--,1); } return 0; }
时间: 2024-10-09 11:07:56