题目大意
有 n 只兔子在一个数轴上,兔子为了方便起见从 1 到 n 标号,第 i 只兔子的初始坐标为 xi(不保证单增不保证非负不保证无重复)。兔子会以以下的方式在数轴上锻炼:一轮包含 m 个跳跃,第j个是兔子a[j] (2≤a[j]≤N−1,a是给出的长度为m的数组) 跳一下,这一下从 兔子a[j]− 1 和 兔子a[j] + 1 中等概率的选一个(假设选了 x),那么 a[j]号兔子 会跳到它当前坐标关于x的坐标的对称点。(注意,即使兔子的位置顺序变化了,但是编号仍保持不变,这里按兔子编号算)兔子会进行k轮跳跃,对每个兔子,请你求出它最后坐标的期望值。
解法
不难发现,兔子i跳跃之后,它与兔子i-1的期望距离会与兔子i+1交换。
所以我们把期望距离单独出来,每个期望距离大小不变,但是期望距离会交换位置,设dis[i]=x[i]-x[i-1],我们用一个id数组表示该距离是第几个兔子与前一个的距离,即:一开始id[i]=i,若兔子i跳,则交换id[i]和id[i+1],若id[i]=x,那么表示x号兔子与x-1号兔子的距离是dis[i](代码中dis[i]表示为a[i])
一轮进行过后我们得到了一个id数组,不难发现这其实是个置换,换k次,所以再找置换的环然后每个环处理一下,得出最终的id数组,把dis求前缀和就是答案。
代码
%%%集训队大佬武弘勋的代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int gi() {
int x=0,o=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if(ch=='-') o=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*o;
}
int n,m,id[N],st[N],top=0;
ll a[N],ans[N],k;
bool vis[N];
int main() {
//freopen("rabbit.in","r",stdin);
//freopen("rabbit.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++) a[i]=gi(),id[i]=i;
for(int i=n;i;i--) a[i]-=a[i-1];
cin>>m>>k;
for(int i=1,x;i<=m;i++) x=gi(),swap(id[x],id[x+1]);
for(int i=1;i<=n;i++)
if(!vis[i]) {
top=0;
for(int j=i;!vis[j];j=id[j]) st[++top]=j,vis[j]=1;
for(int j=1;j<=top;j++) ans[st[j]]=a[st[(k+j-1)%top+1]];
}
for(int i=1;i<=n;i++) ans[i]+=ans[i-1],printf("%lld\n",ans[i]);
return 0;
}