https://ac.nowcoder.com/acm/contest/5671/J
牛客多校j题,利用线段树nlogn写出模拟的操作快速幂
可以类似给转圈用
#include<iostream> #include<set> using namespace std; typedef long long ll; const int maxn = 2e5+11; int list[maxn]; int vis[maxn]; int a[maxn]; set<int>ins; set<int>::iterator it; int n,m; /* cnt--; p = (p%cnt + k - 1)%cnt; */ int tree[maxn*4]; int update(int node,int be,int en,int i,int val) { int l = node*2; int r = node*2+1; int mid = be+en>>1; if(be == en) { tree[node] = val; return 0; } if(i <= mid) update(l,be,mid,i,val); else update(r,mid+1,en,i,val); tree[node] = tree[l] + tree[r]; return 0; } int ans; int qurry(int node,int be,int en,int sum) { int l = node*2; int r = node*2+1; int mid = be+en>>1; if(be == en) { tree[node] --; ans = be; return 0; } if(sum <= tree[l]) { qurry(l,be,mid,sum); } else { qurry(r,mid+1,en,sum - tree[l]); } tree[node] = tree[l] + tree[r]; return 0; } int cal(int *list,int *a) { //按照a的规则跑 for(int i=1; i<=n; i++) { vis[i] = list[a[i]]; } for(int i=1; i<=n; i++) { list[i] = vis[i]; } return 0; } int main() { scanf("%d %d",&n,&m); for(int i=1; i<=n; i++) { list[i] = i; update(1,1,n,i,1); } while(m--) { int k,x; scanf("%d %d",&k,&x); int p = k-1; int cnt = n; for(int i=1; i<n; i++) { qurry(1,1,n,p+1); a[i] = ans; cnt--; p = (p%cnt + k - 1)%cnt; } qurry(1,1,n,p+1); a[n] = ans; for(int i=1;i<=n;i++){ update(1,1,n,i,1); } while(x){ if(x&1){ cal(list,a); } x>>=1; cal(a,a); } } for(int i=1; i<=n; i++) { printf("%d ",list[i]); } printf(" "); return 0; }