专题班前缀和练习题 - F - 牛牛的猜球游戏

要求 [L,R] 区间的运算,怎么在 O(1) 的时间内,利用 [1,R] 与 [1, L-1] 的结果算出来
A 思路:矩阵
这是 N 个杯子,N 个球,建立一个 N * N 的矩阵,每进行一次操作,杯子交换也好,球移动也好,就是进行一次矩阵乘法运算。所以不管运算多少次,只要记得 [1, L-1] 和 [1,R] 的操作。
乘 [1,R], 除 [1, L-1]即可。当然,除在矩阵中,就是乘逆矩阵。矩阵代码会很麻烦。
B 思路:群论
把(0,1,2,3,4,5,6,7,8,9)想成一个圈
无论怎么换,都是在这个圈中对元素进行交换。找到某种方法,对区间 [1, L-1] 的操作取消即可。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 20;
int s[maxn][20], n, m, a, b, ans[20], tmp[20];

int main(){
    //freopen("input.txt", "r", stdin);
    scanf("%d%d", &n, &m);
    memset(s, 0, sizeof(s));
    for(int j = 0; j <= 9; j++)
        s[0][j] = j;
    for(int i = 1; i <= n; i++){
        scanf("%d%d", &a, &b);
        for(int j = 0; j <= 9; j++)
            s[i][j] = s[i - 1][j];
        swap(s[i][a], s[i][b]);
    }
    for(int k = 1; k <= m; k++){
        scanf("%d%d", &a, &b);
        for(int l = 0; l <= 9; l++)
            tmp[s[a-1][l]] = l;
        for(int l = 0; l <= 9; l++)
            ans[l] = tmp[s[b][l]];
        for(int l = 0; l <= 9; l++)
            printf("%d%c", ans[l], l == 9 ? '\n': ' ');
    }
    return 0;
}


    for(int _ = 1; _ <= m; _++){
        scanf("%d%d", &a, &b);
        for(int j = 0; j <= 9; j++)
            for(int k = 0; k <= 9; k++)
                if (s[a - 1][j] == s[b][k]){
                    ans[k] = j;
                    break;
                }
        for(int l = 0; l <= 9; l++)
            printf("%d%c", ans[l], l == 9 ? '\n': ' ');
    }

第一种代码,就是说,去找还原。
第二种代码,就是暴力询问,在 [1, R] 之后,去找到 [L-1] 的杯子。
第二种可能好理解一些,但是多了一个常数级别。

全部评论

相关推荐

点赞 评论 收藏
转发
中国平安 Java开发 12.5*16
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务