Atcoder Grand 006 C-Rabbit Exercise
题意:
数轴上有n只兔子,第i只兔子的坐标为xi。
有一组操作,这组操作的第i个操作是要让第ai只兔子等概率的跳到自己关于第ai+1或第ai-1只兔子的对称点。
进行K组操作,求每只兔子最后坐标的期望值。
当第一只兔子$i$跳完,它的位置的期望是$x[i+1]+x[i-1]-x[i]$。
然后我们发现当有其他一只兔子$j$要以$i$为对称轴跳跃时$j$跳完坐标的期望就是以$i$的期望坐标为对称轴跳跃到的坐标。
所以每次相当于让$x[i]=x[i+1]+x[i-1]-x[i]$。
我们维护差分序列,每次相当于交换了相邻两个数。
先做完一组,得到了一个排列,之后连边找环,就能知道跳k组后的位置了。
#include<bits/stdc++.h>
#define N 100005
#define int long long
using namespace std;
int n,m,x[N],a[N],p[N],s[N],cnt;
long long k;
int be[N],num[N],v[N];
vector<int>q[N];
void dfs(int x,int dep)
{
num[x]=dep;v[x]=1;be[x]=cnt;
q[cnt].push_back(x);
if(!v[p[x]])dfs(p[x],dep+1);
}
signed main()
{
memset(v,0,sizeof(v));
cin>>n;
for(int i=1;i<=n;i++)cin>>x[i];
for(int i=1;i<n;i++)s[i]=x[i+1]-x[i];
cin>>m>>k;
for(int i=1;i<n;i++)p[i]=i;
for(int i=1;i<=m;i++){cin>>a[i];swap(p[a[i]],p[a[i]-1]);}
for(int i=1;i<n;i++)if(!v[i])cnt++,dfs(i,0);
cout<<x[1]<<endl;
int now=x[1];
for(int i=1;i<n;i++)
{
now+=s[q[be[i]][(num[i]+k)%q[be[i]].size()]];
cout<<now<<endl;
}
return 0;
}