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;
    }
  • 相关阅读:
    SCAU 9504 面试
    SCAU 9503 懒人选座位
    SCAU 8628 相亲
    SCAU 10691 ACM 光环
    SCAU 8626 原子量计数
    SCAU 10674 等差对
    HDU ACM 1048 The Hardest Problem Ever (水题)
    SCAU 9502 ARDF
    SCAU 10686 DeathGod不知道的事情
    SCAU 8629 热身游戏(高精度)
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270320.html
Copyright © 2011-2022 走看看