线段树 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;
}

  

原文地址:https://www.cnblogs.com/EchoZQN/p/11340770.html