• bzoj 2054/2375. 疯狂的涂色


    bzoj 2054/bzoj 2375

    Description

    给定一个长度为 (n) 的序列,共 (m) 次操作,再给定两个数 (p)(q),每次把 ((i*p+q))%(n+1)((i*q+p))%(n+1) 之间的点染上颜色 (i) ,被染过色的会被新颜色覆盖,求最后每个点的颜色。

    (n,m≤10^7)

    Solution

    Solution 1 (TLE) code

    我会暴力!

    暴力从第1次操作到第m次往后覆盖,最后直接输出。

    时间复杂度 (O(mn))似乎一个点过不掉。

    Solution 2 (TLE) code

    考虑最简单的优化。

    与铺地毯相同,这题也是只要求出最后的状态。

    所以可以从后往前枚举,每次只对区间中没有染过色的点进行染色,染过的就不用管了,染到每个位置全部有色为止。

    最坏时间复杂度:(O(mn)),可以水过一点数据。

    轻易卡掉这个算法的数据:(m) 开到很大且其中有一个格子始终没有被涂上色。

    Solution 3 (AC)

    此题m巨大,肯定不能挨个处理一遍。考虑能不能在算法2的基础上再优化。

    发现在算法2中,每次寻找没有染过色的店是直接暴力查找,这样很浪费时间。

    设一个并查集,(fa[i] = x) 定义为指向第 (i)号格子后面下一个没有涂色格子的位置为 (x)

    仍然是倒序枚举,如果这次要把第 (x) 号格子给染了,那就指向后面一个位置的 (fa) 值(即指向 (find(x + 1)))。

    最后就是如何判断是否全部染色完了。可以新增一个计数器,每染一个点就 (+1),加到 (n) 就退出。

    时间复杂度:(O(M))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int M = 1E6 + 5;
    int n, m, p, q;
    int b[M];//b数组表示每个格子染色的状态
    int fa[M];
    int find(int x)
    {
    	if(fa[x] == x)
    	{
    		return x;
    	}
    	else
    	{
    		return fa[x] = find(fa[x]);
    	}
    }
    int main()
    {
    	cin >> n >> m >> p >> q;
    	int cnt = 0;
    	for(int i = 1; i <= n + 1; i++)
    	{
    		fa[i] = i;
    	}
    	for(int i = m; i >= 1; i--)
    	{
    		int l = (p * i + q) % n + 1;
    		int r = (q * i + p) % n + 1;//根据题意计算区间左右端点
    		if(l > r)
    		{
    			swap(l, r);
    		}
    		for(int j = find(l); j <= r; j = find(j))//只要在这个区间内就不停向后找未染色的点
    		{
    
    			b[j] = i;
    			fa[j] = j + 1;
    			cnt++;
    		}
    		if(cnt == n)//如果全部染好色了提前退出
    		{
    			break;
    		} 
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		printf("%d
    ", b[i]);
    	}
    }
    
  • 相关阅读:
    selenium 18种元素定位方法
    python3+selenium配置可能报错记录
    adb+monkey压力测试入门
    appscan使用教程(全)
    appium---android元素定位
    QTP自动化测试
    postman Could not get any response。
    Jmeter接口测试+压力测试
    Android 偏门xml属性
    CrashHandler
  • 原文地址:https://www.cnblogs.com/pjxpjx/p/15086346.html
Copyright © 2020-2023  润新知