分析
这题就是要求,每次查找并弹出第k大元素
$k=\sum r_i$%剩余元素数量 +1
然后这种操作不难想到平衡树权值线段树
删点乱搞一下就行了
顺便说比赛的时候写了平衡树,结果没看出来可以%转变,直接用平衡树模拟了放牌……更不可思议的是这么久没写了居然写出来的东西能出正确答案
这题出题人很阴险啊,Splay加了快读和氧气才90,然后脑子一抽想用树状数组……更慢
线段树 100pts

#include <iostream>
#include <cstdio>
using namespace std;
const int N=7e5+10;
struct Seg {
int c[2],sz;
}t[4*N];
int rt=1,n,r;
void Update(int x) {
t[x].sz=t[t[x].c[0]].sz+t[t[x].c[1]].sz;
}
void Build(int x,int l,int r) {
if (l==r) {
t[x].sz=1;
return;
}
int mid=l+r>>1;
Build(t[x].c[0]=x<<1,l,mid);
Build(t[x].c[1]=(x<<1)+1,mid+1,r);
Update(x);
}
void Find_Del(int x,int l,int r,int k,int from) {
if (l==r) {
printf("%d\n",l);
t[x>>1].c[from]=0;
return;
}
int mid=l+r>>1;
if (t[x].c[0]&&t[t[x].c[0]].sz>=k) Find_Del(t[x].c[0],l,mid,k,0);
else if (t[x].c[1]&&t[t[x].c[1]].sz>=k-t[t[x].c[0]].sz) Find_Del(t[x].c[1],mid+1,r,k-t[t[x].c[0]].sz,1);
Update(x);
}
int main() {
scanf("%d",&n);
Build(rt,1,n);
for (int i=1;i<=n;i++) {
int R;
scanf("%d",&R);r=(R+r)%(n-i+1);
Find_Del(rt,1,n,r+1,666);
}
}
Splay O(2) 90pts

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
using namespace std;
const int N=7e5+10;
struct Node {
int c[2],f,id,sz;
}t[N];
int rt,cnt;
int n,r;
bool a[N];
int Read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
bool Witch(int x) {return t[t[x].f].c[1]==x;}
void Update(int x) {
t[x].sz=1+t[t[x].c[0]].sz+t[t[x].c[1]].sz;
}
void Rotate(int x) {
int f=t[x].f,gf=t[f].f,lr=Witch(x);
t[x].f=gf;if (gf) t[gf].c[Witch(f)]=x;
t[t[f].c[lr]=t[x].c[lr^1]].f=f;
t[t[x].c[lr^1]=f].f=x;
Update(f);Update(x);
}
void Splay(int x,int goal) {
for (;t[x].f!=goal;Rotate(x))
if (t[t[x].f].f!=goal) Rotate(Witch(t[x].f)==Witch(x)?t[x].f:x);
if (!goal) rt=x;
}
void Build(int &x,int l,int r) {
int mid=l+r>>1;
if (a[mid]) return;
if (!x) x=++cnt;
t[x].id=mid;t[x].sz=1;a[mid]=1;
Build(t[x].c[0],l,mid);
Build(t[x].c[1],mid+1,r);
t[x].sz+=t[t[x].c[0]].sz+t[t[x].c[1]].sz;
if (t[x].c[0]) t[t[x].c[0]].f=x;
if (t[x].c[1]) t[t[x].c[1]].f=x;
}
int Get_Kth(int x,int k) {
if (t[t[x].c[0]].sz+1>k) return Get_Kth(t[x].c[0],k);
else {
if (t[t[x].c[0]].sz+1==k) return x;
return Get_Kth(t[x].c[1],k-t[t[x].c[0]].sz-1);
}
}
void Del(int x) {
Splay(x,0);
int oldrt=rt;
printf("%d\n",t[x].id);
if (!t[x].c[0]&&!t[x].c[1]) {
rt=0;return;
}
if (!t[x].c[0]) {
rt=t[x].c[1];t[rt].f=0;t[oldrt].c[1]=0;
return;
}
if (!t[x].c[1]) {
rt=t[x].c[0];t[rt].f=0;t[oldrt].c[0]=0;
return;
}
int p=t[x].c[0];
while (t[p].c[1]) p=t[p].c[1];
Splay(p,0);
rt=p;t[t[rt].c[1]=t[oldrt].c[1]].f=rt;
t[oldrt].f=t[oldrt].c[1]=0;
Update(rt);
}
int main() {
n=Read();
Build(rt,1,n);
for (int i=1;i<=n;i++) {
int R;
R=Read();(r+=R)%=cnt;
Del(Get_Kth(rt,r+1));cnt--;
}
cnt++;
}
树状数组 O(2) 约60pts

#include <iostream>
#include <cstdio>
using namespace std;
#define lowbit(x) x&-x
const int N=7e5+10;
int t[N];
int n,R;
void Add(int x) {
for (;x<=n;x+=lowbit(x)) t[x]++;
}
void Dec(int x) {
for (;x<=n;x+=lowbit(x)) t[x]--;
}
int Sum(int x) {
int ans=0;
for (;x;x-=lowbit(x)) ans+=t[x];
return ans;
}
int main() {
scanf("%d",&n);
for (int i=1;i<=n;i++) Add(i);
for (int i=1;i<=n;i++) {
int r;
scanf("%d",&r);R=(R+r)%(n-i+1);
int j=R+1;
while (Sum(j)!=R+1) j+=R+1-Sum(j);
printf("%d\n",j);
Dec(j);
}
}
来源:https://www.cnblogs.com/mastervan/p/11123216.html
