zoukankan      html  css  js  c++  java
  • 牛客练习赛25 C 再编号

    解题思路

    我们先来观察一下题目中给出的公式

    $$a'_i=(sum_{j=1}^na_j)-a_i$$

    通过这个公式推一下经过再编号后的序列的总和,因为我们推出这个和之后可以进行下一次计算。

    $$sum_{i=1}^na'_i=sum_{i=1}^n((sum_{j=1}^na_j)-a_i)$$

    变形一下

    $$sum_{i=1}^na'_i=n imes (sum_{j=1}^na_j)-sum_{i=1}^na_i$$

    $$sum_{i=1}^na'_i=(n-1) imes sum_{i=1}^na_i$$

    emmmm,这个结论貌似很有用的样子,我们可以通过上面的推导预处理处每一次变化后整个序列的总和。

    在观察一下原来的序列,每一次再编号他们的每个数和第一个数的差的绝对值是不变的。并且在奇数次的变化后为$a_1-a_j$,偶数次变化后是$a_j-a_1$。

    既然是这样子,那我们就可以再通过之前预处理的总和在处理出每一次改变后的第一个值。通过这个值我们可以$O(1)$的对每一个位置上的数值进行询问。

    这样的话总时间复杂度是$O(t)$的

    代码看这里

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <vector>
    using namespace std;
    #define LL long long
    #define mod int(1e9+7)
    LL a[100010],n,m,sum[100100];
    LL ans[100001][2],num;
    int main()
    {
        LL x,t;
        scanf("%lld%lld%lld",&n,&m,&a[1]);
        num=a[1];
        for(int i=2;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            num+=a[i];
            sum[i]=a[1]-a[i];
        }
        ans[0][1]=a[1];
        for(int i=1;i<=100001;i++)
        {
            ans[i][1]=((num-a[1])+2*mod)%mod;
            a[1]=ans[i][1];
            num=(num*(n-1))%mod;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%lld%lld",&x,&t);
            if(t%2!=0)printf("%lld
    ",(ans[t][1]+sum[x]+mod)%mod);
            else printf("%lld
    ",(ans[t][1]-sum[x]+mod)%mod);
        }
    }
  • 相关阅读:
    Xcode8中Swift3.0适配问题
    Swift3.0语法变化
    一起聊聊 Swift 3.0
    Swift 3.0 的 open,public,internal,fileprivate,private 关键字
    leetcode先刷_Binary Tree Level Order Traversal II
    java + memcached安装
    POJ 2533-Longest Ordered Subsequence(DP)
    网络协议——IP
    使用百度地图——入门
    取消延时功能
  • 原文地址:https://www.cnblogs.com/bljfy/p/9532789.html
Copyright © 2011-2022 走看看