zoukankan      html  css  js  c++  java
  • [Comet OJ

    C 给定1000*1000的矩阵,每次将一个子矩阵内全部值赋值为1,问四联通块数量 Q 3e4

    首先考虑复杂度,3e4次操作的合并暴力肯定不行,并且要考虑已经为1的块不应该再次考虑

    1.考虑合并操作,对于一个0点,当他变为1对答案的影响只有几种情况

    周边都是0,总联通联通块数量加1

    周边有(1 - 4)个不同联通块,ans -= 不同联通块个数+1

    对于相同的联通块通过当前0点合并没有意义,不用计算。

    所以对于每个0点的合并可以快速计算并用并查集合并(映射下标)

    2.然后考虑第二个问题,如何让每个0点只被操作一次

    可以用并查集维护每行当前点的下一个0点,这样在区间上跳动速度飞快并且每次跳的都是0点

    或者用set维护当前行内还有0的下标并操作erase(比并查集常数大)

    /*
        Zeolim - An AC a day keeps the bug away
    */
     
    //#pragma GCC optimize(2)
    //#pragma GCC ("-W1,--stack=128000000")
    #include <bits/stdc++.h>
    using namespace std;
    #define mp(x, y) make_pair(x, y)
    #define fr(x, y, z) for(int x = y; x < z; ++x)
    #define pb(x) push_back(x)
    #define mem(x, y) memset(x, y, sizeof(x))
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    typedef std::pair <int, int> pii;
    typedef std::vector <int> vi;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const ll MOD = 386910137;
    const ull P = 13331; 
    const int MAXN = 3e6 + 100;
    
    int n, m;
    int fa[MAXN] = {0};
    int mov[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    bool arr[1010][1010] = {0};
    
    struct uni
    {
    	int fa[1010] = {0};
    	uni() { for(int i = 0; i < 1010; ++i) fa[i] = i; }
    	int findfa(int x) { return x == fa[x] ? x : fa[x] = findfa(fa[x] ); }
    }u[1010];
    
    int findfa(int x) { return fa[x] == x ? x : fa[x] = findfa(fa[x]); }
    
    int ans = 0;
    int getp(int x, int y) { return x * m + y; }
    struct node { int x, y, fa; };
    
    void uni(int x, int y)
    {
    	++ans;  
    	int tox, toy, p, q;
    	p = findfa(getp(x, y));
    	
    	for(int i = 0; i < 4; ++i) //统计不同联通块的数量并计算贡献 
    	{
    		tox = x + mov[i][0], toy = y + mov[i][1];
    		if(arr[tox][toy])
    		{
    			q = findfa(getp(tox, toy)); 
    			if(p != q) { fa[q] = p; --ans; } //不同联通块才有贡献 
    		}		
    	}
    }
    
    void init()
    {
    	for(int i = 0; i < 1010; ++i)
    		for(int j = 0; j < 1010; ++j)
    			fa[getp(i, j)] = getp(i, j);
    			
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= m; ++j) //维护第i行第j列后面的第一个0 
    		{
    			if(!arr[i][j]) u[i].fa[j] = j;
    			else u[i].fa[j] = j + 1;
    		}
    	}
    	 
    	for(int i = 1; i <= n; ++i) //初始化合并矩阵信息 
    	{
    		for(int j = 1; j <= m; ++j)
    		{
    			if(!arr[i][j]) continue;
    			uni(i, j);
    		}
    	}
    }
    
    void put()
    {
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= m; ++j)
    		{
    			cout << arr[i][j];
    		}
    		cout << '
    ';
    	}
    }
    
    int main()
    {  
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        //freopen("d:out.txt","w",stdout);
        //freopen("d:in.txt","r",stdin);
        
    	cin >> n >> m; 
    	
    	char x;
    		
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= m; ++j)
    		{
    			cin >> x;
    			arr[i][j] = (x == '1');
    		}
    	}
    	
    	init();
    	
    	//cout << ans << '
    ';
    	
    	int q;
    	
    	cin >> q;
    	
    	while(q--)
    	{
    		int x1, y1, x2, y2;
    		cin >> x1 >> y1 >> x2 >> y2;
    		
    		for(int i = x1; i <= x2; ++i) //操作区间内1 
    		{
    			for(int j = u[i].findfa(y1); j <= y2; j = u[i].findfa(j))
    			{
    				arr[i][j] = 1;
    				u[i].fa[j] = j + 1;
    				uni(i, j);
    			}
    		}
    		
    		//put();
    		cout << ans << '
    ';
    	}
    	
        
        return 0;
    }

    B 贪吃蛇,wsad上下左右移动,吃住x头变长,不吃整体移动,问最终形态

    用双端队列可以很容易的维护当前状态见代码

    /*
        Zeolim - An AC a day keeps the bug away
    */
     
    //#pragma GCC optimize(2)
    //#pragma GCC ("-W1,--stack=128000000")
    #include <bits/stdc++.h>
    using namespace std;
    #define mp(x, y) make_pair(x, y)
    #define fr(x, y, z) for(int x = y; x < z; ++x)
    #define pb(x) push_back(x)
    #define mem(x, y) memset(x, y, sizeof(x))
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    typedef std::pair <int, int> pii;
    typedef std::vector <int> vi;
    //typedef __int128 ill;
    const ld PI = acos(-1.0);
    const ld E = exp(1.0);
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const ll MOD = 386910137;
    const ull P = 13331; 
    const int MAXN = 3e6 + 100;
    int mov[4][2] = {{0, 1},{1, 0},{-1,0},{0,-1}};
    struct pit { int x, y; };
    char arr[410][410] = {0};
    int n, m;
    bool inmap(int x, int y) { return (x >= 1 && x <= n && y >= 1 && y <= m); }
    int main()
    {  
        
        cin >> n >> m;
        deque <pit> Q;
        for(int i = 1; i <= n; ++i)
        {
        	for(int j = 1; j <= m; ++j)
        	{
        		cin >> arr[i][j];
        		if(arr[i][j] == '@')
        		{
        			Q.push_back(pit{i, j});
        			arr[i][j] = '.';
    			}
    		}
    	}
    	map <char, int> MP;
    	MP['W'] = 2, MP['A'] = 3, MP['S'] = 1, MP['D'] = 0;
    	string opt;
    	cin >> opt;
    	int p, tox, toy, rtox, rtoy;
    	for(auto x : opt)
    	{
    		p = MP[x], tox = Q.front().x, toy = Q.front().y;
    		tox += mov[p][0], toy += mov[p][1];
    		if(!inmap(tox, toy)) { cout << "GG
    "; return 0; }
    		if(arr[tox][toy] == 'o') 
    		{
    			arr[tox][toy] = '.';
    			Q.push_front(pit{tox, toy});
    		}
    		else
    		{
    			rtox = Q.back().x, rtoy = Q.back().y;
    			Q.pop_back();
    			Q.push_front(pit{tox, toy});
    			rtox = Q[1].x, rtoy = Q[1].y;
    		}
    	}
    	
    	while(Q.size() > 1)
    	{
    		arr[Q.back().x][Q.back().y] = 'X';
    		Q.pop_back();
    	}
    	arr[Q.back().x][Q.back().y] = '@';
    	
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= m; ++j)
    		{
    			cout << arr[i][j];
    		}
    		cout << '
    ';
    	}
        return 0;
    }
  • 相关阅读:
    vscode 简介
    TypeScriot 深入
    TypeScript 三斜线指令
    Mysql基础(二十二):表操作:创建,删除,修改,查询表
    Mysql基础(十):函数(四)分组函数
    Mysql基础(九):函数(三)流程控制函数(IF/CASE WHEN)
    Mysql基础(七):函数(一)常见函数/单行函数分类/数学函数/日期函数/其他函数
    Mysql基础(六):sql查询(六)分页查询/联合查询
    Mysql基础(五):sql查询(五)子查询
    Mysql基础(四):sql查询(四)连接查询
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270320.html
Copyright © 2011-2022 走看看