zoukankan      html  css  js  c++  java
  • 【做题】agc006C

    原文链接https://www.cnblogs.com/cly-none/p/9745177.html

    题意:数轴上有(n)个点,从(1)(n)编号。有(m)个操作,每次操作给出一个编号(i \, 1 < i < n),即把点(i)等概率移动到它关于点(i-1)的对称点或关于点(i+1)的对称点。记顺序执行这(m)个操作为完成1次。问完成(k)次后,所有点的坐标的期望值是多少。

    (n, m leq 10^5, \, k leq 10^{18})

    首先,容易得到一个坐标为x的点,关于坐标为y的点对称后,新点的坐标为2y - x。我们记点i的坐标为(p_i),那么对它操作后得到的新点坐标的期望值就是(frac {2p_{i+1} + 2p_{i-1} -2p_i} {2} = p_{i+1} + p_{i-1} - p_i)

    因为期望有线性性,所以我们能确信,每一次操作就是把点(i)的坐标变为(p_{i+1} + p_{i-1} - p_i),最终答案就是每个点的坐标。

    但我们还是难以解决这个问题。考虑这个性质:

    [egin{eqnarray*} p_{i+1} - (p_{i+1} + p_{i-1} - p_i) &=& p_i - p_{i-1}\ (p_{i+1} + p_{i-1} - p_i) - p_{i-1} &=& p_{i+1} - p_i end{eqnarray*} ]

    我们定义(p'_i = p_i - p_{i-1}),那么,我们发现一次操作就是交换了(p'_i)(p'_{i-1})。因此,这(m)个操作就是对(p')做一个置换。我们把每个环抠出来就能得到重复做(k)次置换之后的结果。最好再通过(p')还原出(p)就好了。

    时间复杂度(O(n))

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    typedef long long ll;
    int n,m,p[N],per[N],vis[N],ans[N],lop[N],cnt;
    ll k,val[N],res[N];
    int main() {
      scanf("%d",&n);
      for (int i = 1 ; i <= n ; ++ i)
        scanf("%lld",&val[i]);
      scanf("%d%lld",&m,&k);
      for (int i = 1 ; i <= m ; ++ i)
        scanf("%d",&p[i]);
      for (int i = n ; i >= 1 ; -- i)
        val[i] = val[i] - val[i-1];
      for (int i = 1 ; i <= n ; ++ i)
        per[i] = i;
      for (int i = 1 ; i <= m ; ++ i)
        swap(per[p[i]],per[p[i]+1]);
      for (int i = 1 ; i <= n ; ++ i) {
        if (vis[i]) continue;
        cnt = 0;
        lop[++cnt] = i;
        int pos = per[i];
        while (pos != i) {
          vis[pos] = 1;
          lop[++cnt] = pos;
          pos = per[pos];
        }
        for (int j = 1 ; j <= cnt ; ++ j)
          ans[lop[j]] = lop[(j + k - 1) % cnt + 1];
      }
      for (int i = 1 ; i <= n ; ++ i)
        res[i] = val[ans[i]];
      for (int i = 1 ; i <= n ; ++ i)
        res[i] += res[i-1];
      for (int i = 1 ; i <= n ; ++ i)
        printf("%lld.0
    ",res[i]);
      return 0;
    }
    

    小结:这个特殊性质还是挺难找的。只能说找规律时,考虑差分、前缀和的变化是有用的。

  • 相关阅读:
    三次请求(读-改-读)引出nibernate 一级缓存
    算法竞赛入门经典第一、二章摘记
    uva 10905 Children's Game
    uva 11205 The broken pedometer
    uva 10160 Servicing stations
    uva 208 Firetruck
    uva 167 The Sultan's Successors
    zoj 1016 Parencodings
    uva 307 Sticks
    uva 216 Getting in Line
  • 原文地址:https://www.cnblogs.com/cly-none/p/9745177.html
Copyright © 2011-2022 走看看