zoukankan      html  css  js  c++  java
  • 线段树 C

    这个题目居然可以用线段树写,好震惊,如果不是在线段树专题肯定想不到,但是就算在线段树的专题里面,我也不太会怎么写。

    这个题目大意是,给你n m n代表n个点,m代表m条边,然后就是m行,每行两个数字,一个u一个v。

    这个意思是u和v不想连,然后问你这个n个点形成了多少个联通块。

    思路大概是这样,首先随意枚举一个点,然后直接更新每一个点的值+1,先消除自己的影响,然后对于每一个和它连的点的值都-1

    然后查找一个值大于0 的点,再继续循环这个过程,如果找不到了就推出这个循环。

    这个复杂度我不太会算。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <stack>
    #include <map>
    #include <string>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn = 4e5 + 10;
    int cnt[maxn * 4], maxs[maxn * 4];
    int lazy[maxn * 4];
    
    void push_up(int id)
    {
    	if (maxs[id << 1] < maxs[id << 1 | 1]) {
    		maxs[id] = maxs[id << 1 | 1];
    		cnt[id] = cnt[id << 1 | 1];
    	}
    	else {
    		maxs[id] = maxs[id << 1];
    		cnt[id] = cnt[id << 1];
    	}
    	// printf("cnt[%d]=%d cnt[%d]=%d
    ", id << 1, cnt[id << 1], id << 1 | 1, cnt[id << 1 | 1]);
    	// printf("cnt[%d]=%d
    ", id, cnt[id]);
    }
    
    void build(int id,int l,int r)
    {
    	lazy[id] = 0;
    	if(l==r)
    	{
    		cnt[id] = l;
    		maxs[id] = 0;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(id << 1, l, mid);
    	build(id << 1 | 1, mid + 1, r);
    	push_up(id);
    }
    
    void push_down(int id)
    {
    	//printf("id=%d
    ", id);
    	if (lazy[id] == 0) return;
    	maxs[id << 1] += lazy[id];
    	maxs[id << 1 | 1] += lazy[id];
    	lazy[id << 1] += lazy[id];
    	lazy[id << 1 | 1] += lazy[id];
    	lazy[id] = 0;
    }
    
    void update(int id,int l,int r,const int x,const int y,int val)
    {
    	// printf("id=%d l=%d r=%d x=%d y=%d
    ", id, l, r, x, y);
    	if(x<=l&&y>=r)
    	{
    		maxs[id] += val;
    		lazy[id] += val;
    		return;
    	}
    	push_down(id);
    	int mid = (l + r) >> 1;
    	if (x <= mid) update(id << 1, l, mid, x, y, val);
    	if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, val);
    	push_up(id);
    }
    
    struct node
    {
    	int v, nxt;
    	node(int v=0,int nxt=0):v(v),nxt(nxt){}
    }ex[maxn];
    int head[maxn], tot = 0, num;
    void init()
    {
    	memset(head, -1, sizeof(head));
    	tot = 0, num = 0;
    }
    
    void add(int u,int v)
    {
    	ex[tot] = node(v, head[u]);
    	head[u] = tot++;
    	ex[tot] = node(u, head[v]);
    	head[v] = tot++;
    }
    int a[maxn];
    bool vis[maxn];
    int n, m;
    
    int dfs(int x)
    {
    	int res = 0;
    	build(1, 1, n);
    	while(1)
    	{
    		vis[x] = 1;
    		res++;
    		update(1, 1, n, 1, n, 1);
    		update(1, 1, n, x, x, -inf);
    		for (int i = head[x]; i != -1; i = ex[i].nxt)
    		{
    			int v = ex[i].v;
    			update(1, 1, n, v, v, -1);
    		}
    		// printf("
    
    ");
    		if (maxs[1] <= 0) break;
    		x = cnt[1];
    	}
    	return res;
    }
    
    int main()
    {
    	init();
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= m; i++) {
    		int u, v;
    		scanf("%d%d", &u, &v);
    		add(u, v);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		if (vis[i]) continue;
    		a[num++] = dfs(i);
    	}
    	sort(a, a + num);
    	printf("%d
    ", num);
    	for (int i = 0; i < num; i++) printf("%d ", a[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    centos下tomcat自启动
    navcat12 windows 下载安装
    mysql8 windows 下载安装
    redis windows下载安装
    python json.dumps()函数输出json格式,使用indent参数对json数据格式化输出
    Python的安装图解
    spark入门系列教程二——简单入门实例
    Spark入门系列教程一 —— Spark2.3.1 集群安装
    css在文字两边加线,文字居中效果——实战应用
    a标签中对于邮箱和电话的用法mark
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11340770.html
Copyright © 2011-2022 走看看