牛客网-剩下的树【线段树入门】

在这里插入图片描述
看评论区大佬都水过了,我也先水一下, O ( m n ) O(mn) 复杂度都可以过,可以见得数据之水当然这道题的数据量本身也是符合这个复杂度的

暴力解法

ps:fill和memset别用得太多,有时候会被卡死

//运行时间:5ms 占用内存:544k
#include<iostream>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
using namespace std;

#define ll int
#define MAX 10005
#define inf 0x3fffff

ll arr[MAX];

int main() {
	ll L, M, a, b;
	while (cin >> L >> M) {
		fill(arr, arr + MAX, 1);
		for (int i = 0; i < M; i++) {
			cin >> a >> b;
			for (int i = a; i <= b; i++)arr[i] = 0;
		}
		ll res = 0;
		for (int i = 0; i <= L; i++)res += arr[i];
		cout << res << endl;
	}
}

线段树

但是如果 N = 100000 N=100000 , M = 10000 M=10000 ?还能水过嘛,显然不能,对于区间查询,区间修改,最好的方式即线段树。这道题的线段树更新也比较简单,具体还是看

#include<iostream>
#include<string>
#include<string.h>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
using namespace std;

#define ll int
#define MAX 10005
#define inf 0x3fffff

ll t[MAX * 4], tag[MAX * 4];
inline ll lc(ll k) { return k << 1; }
inline ll rc(ll k) { return k << 1 | 1; }

void pushUpSum(ll p) { t[p] = t[lc(p)] + t[rc(p)]; }
void build(ll p, ll l, ll r){
	if (l == r) { t[p] = 1; return; }
	ll mid = (l + r) >> 1;
	build(lc(p), l, mid); 
	build(rc(p), mid + 1, r);
	pushUpSum(p);

}

inline void f(ll p, ll l, ll r, ll k) {
	tag[p] = k;
	t[p] = 0;//这里pushdown是清零操作
	if (t[p] < 0)t[p] = 0;
}
inline void pushDown(ll p, ll l, ll r) {
	ll mid = (l + r) >> 1;
	f(lc(p), l, mid, tag[p]);
	f(rc(p), mid + 1, r, tag[p]);
	tag[p] = 0;
}

inline void update(ll nl, ll nr, ll l, ll r, ll p, ll k = -1) {
	//nl-nr:需要进行-1修改的区间
	//l,r,p,k:当前节点所存储的区间以及节点的编号 
	if (nl <= l && r <= nr) {//需要修改区间包含了当前区间
		t[p] = 0; tag[p] = -1; return;//当前区间清零
	}
	if (tag[p] == -1)pushDown(p, l, r);
	ll mid = (l + r) >> 1;
	if (nl <= mid)update(nl, nr, l, mid, lc(p));
	if (nr > mid)update(nl, nr, mid + 1, r, rc(p));
	pushUpSum(p);
}

int main() {
	ll L, M, a, b;
	while (cin >> L >> M) {
		memset(t, 0, sizeof(t));
		memset(tag, 0, sizeof(tag));
		build(1, 0, L);
		for (int i = 0; i < M; i++) {
			cin >> a >> b;
			update(a, b, 0, L, 1);
		}
		cout << t[1] << endl;
	}
}
发布了269 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105632729