这个题目居然可以用线段树写,好震惊,如果不是在线段树专题肯定想不到,但是就算在线段树的专题里面,我也不太会怎么写。
这个题目大意是,给你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; }