1. 程式人生 > >題解-AtCoder-agc006C Rabbit Exercise

題解-AtCoder-agc006C Rabbit Exercise

getchar exe etc 初始 task space \n 大小 line

Problem

AtCoder & bzoj

題意:數軸上有\(n\)個點(初始坐標均為整數),編號為\(1\)~\(n\)。給出\(m\)個操作。
每個操作會選定點\(a\),然後隨機在點\(a-1\)和點\(a+1\)中選一個,將點\(a\)以選中的點為中心做對稱,將這\(m\)個操作按順序執行\(k\)遍(\(1\)~\(m\)完整執行一次算\(1\)遍),求最終每個點的位置的期望值

Solution

不難發現根據期望的線性型,在\(a-1\)\(a+1\)之間隨機選一個進行對稱操作的期望等價於在\(a-1\)\(a+1\)的中點處進行對稱

則我們發現,對於點\(B\)在點\(A\)

\(C\)之間,若\(A\)\(B\)距離為\(a\),若\(B\)\(C\)距離為\(b\),則對稱後的位置\(B‘\)\(A\)距離為\(b\),與\(C\)距離為\(a\)(如下圖)

技術分享圖片

發現如果我們用一個差分數組\(d_i=a_{i+1}-a_i\)存下\(a_i\)數組的話,對稱操作相當於交換\(d_i,d_{i+1}\)

發現進行一輪操作後,整個序列會成為若幹個對換環(一個對換環相當於將整個環旋轉一格再重新賦值),而進行\(k\)次操作相當於將所有環旋轉\(k\)

發現如果整個環的大小為\(c\),則環旋轉\(k\)次和旋轉\(k\bmod c\)次是等價的,則復雜度與\(k\)

無關,整體復雜度\(O(n+m)\)

Code

#include <algorithm>
#include <cstdio>
#include <cctype>
using namespace std;
typedef long long ll;
#define rg register

template <typename _Tp> inline _Tp read(_Tp&x){
    char c11=getchar(),ob=0;x=0;
    while(c11^‘-‘&&!isdigit(c11))c11=getchar();if(c11==‘-‘)ob=1,c11=getchar();
    while(isdigit(c11))x=x*10+c11-‘0‘,c11=getchar();if(ob)x=-x;return x;
}

const int N=101000;
int a[N],vis[N],st[N];
ll b[N],p[N],k;
int n,m,tp;

void init();void work();void print();
int main(){init();work();print();return 0;}

void work(){
    int x;
    for(rg int i=1;i<=m;++i)read(x),swap(a[x],a[x+1]);
    for(rg int i=1;i<=n;++i)if(!vis[i]){
        vis[st[0]=x=i]=tp=1;
        while(!vis[a[x]])
            vis[st[tp++]=x=a[x]]=1;
        int e=k%tp;
        for(rg int j=0;j<tp;++j)
            b[st[j]]=p[st[j+e<tp?j+e:j+e-tp]];
    }
}

void print(){
    ll sm(0ll);
    for(rg int i=1;i<=n;++i)
        printf("%lld\n",sm+=b[i]);
}

void init(){
    read(n);
    for(rg int i=1;i<=n;++i)read(p[i]),a[i]=i;
    for(rg int i=n;i;--i)p[i]-=p[i-1];
    read(m),read(k);
}

題解-AtCoder-agc006C Rabbit Exercise