zoukankan      html  css  js  c++  java
  • CF1458C Latin Square

    CF1458C Latin Square

    题目来源:Codeforces, Codeforces Round #691 (Div. 1), CF#691, CF1458C Latin Square

    题目链接

    本题题解

    发现 ( exttt{RLDU})( exttt{IC}) 是完全不同的两类操作,将它们同时维护很困难。

    本题的突破口是:初始时的每个格子,最终都会恰好对应答案里的一个格子。于是我们拆开来考虑每个格子对答案的“贡献”。

    把一个格子看成三元组 ((i,j,a_{i,j})),考虑一次操作会对这个三元组产生什么样的影响:

    • ( exttt{R})((x, y, z) o (x,y + 1, z))。注意,这里的加法是在 (mod n) 意义下的,下同。
    • ( exttt{L})((x, y, z) o (x, y - 1, z))。注意,这里的减法是在 (mod n) 意义下的,下同。
    • ( exttt{D})((x, y, z) o (x + 1, y, z))
    • ( exttt{U})((x, y, z) o (x - 1, y, z))
    • ( exttt{I})((x, y, z) o (x, z, y))。即交换 2, 3 两项。
    • ( exttt{C})((x, y, z) o (z, y, x))。即交换 1, 3 两项。

    发现转化后,这 (6) 种对三元组进行的操作,是“可合并”的。

    具体地,我们遍历要进行的 (m) 个操作,就能预处理出:依次进行这些操作后,任意一个初始三元组会产生什么变化。

    然后枚举每个格子,将预处理出的变化作用于这个格子上,就能知道这个格子最终对答案的贡献是什么。

    时间复杂度 (mathcal{O}(m + n^2))

    参考代码

    建议使用快速输入、输出,详见本博客公告。

    // problem: CF1458C
    #include <bits/stdc++.h>
    using namespace std;
    
    #define pb push_back
    #define mk make_pair
    #define lob lower_bound
    #define upb upper_bound
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    
    typedef unsigned int uint;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    
    template<typename T> inline void ckmax(T& x, T y) { x = (y > x ? y : x); }
    template<typename T> inline void ckmin(T& x, T y) { x = (y < x ? y : x); }
    
    const int MAXN = 1000;
    const int MAXM = 1e5;
    
    int n, m;
    int a[MAXN + 5][MAXN + 5];
    char s[MAXM + 5];
    
    int ord[4], val[4], res[4];
    int ans[MAXN + 5][MAXN + 5];
    
    void solve_case() {
    	cin >> n >> m;
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= n; ++j) {
    			cin >> a[i][j];
    		}
    	}
    	cin >> (s + 1);
    	
    	ord[1] = 1;
    	ord[2] = 2;
    	ord[3] = 3; // 三元组 (i, j, a[i][j])
    	val[1] = val[2] = val[3] = 0;
    	for (int i = 1; i <= m; ++i) {
    		if (s[i] == 'R') {
    			val[ord[2]]++;
    		} else if (s[i] == 'L') {
    			val[ord[2]]--;
    		} else if (s[i] == 'D') {
    			val[ord[1]]++;
    		} else if (s[i] == 'U') {
    			val[ord[1]]--;
    		} else if (s[i] == 'I') {
    			swap(ord[2], ord[3]);
    		} else if (s[i] == 'C') {
    			swap(ord[1], ord[3]);
    		} else {
    			assert(0);
    		}
    	}
    	// cerr << "changes in val: " << val[1] << " " << val[2] << " " << val[3] << endl;
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= n; ++j) {
    			// (i, j, a[i][j])
    			
    			for (int k = 1; k <= 3; ++k) {
    				if (ord[k] == 1) {
    					res[k] = i + val[1];
    				} else if (ord[k] == 2) {
    					res[k] = j + val[2];
    				} else if (ord[k] == 3) {
    					res[k] = a[i][j] + val[3];
    				}
    				
    				res[k] = (res[k] % n + n) % n;
    				if (res[k] == 0)
    					res[k] = n;
    			}
    			
    			// cerr << "** " << res[1] << " " << res[2] << " " << res[3] << endl;
    			ans[res[1]][res[2]] = res[3];
    		}
    	}
    	for (int i = 1; i <= n; ++i) {
    		for (int j = 1; j <= n; ++j) {
    			cout << ans[i][j] << " 
    "[j == n];
    		}
    	}
    }
    int main() {
    	int T; cin >> T; while (T--) {
    		solve_case();
    	}
    	return 0;
    }
    
  • 相关阅读:
    BZOJ3674:可持久化并查集加强版
    BZOJ3772:精神污染
    BZOJ3932:[CQOI2015]任务查询系统
    BZOJ3123:[SDOI2013]森林
    BZOJ1926:[SDOI2010]粟粟的书架
    029 列表类型内置方法
    02 Python爬虫之盗亦有道
    01 Python爬虫之Requests库入门
    028 字符串类型内置方法
    027 数字类型内置方法
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/14163636.html
Copyright © 2011-2022 走看看