#include<iostream>#include<cstdio>usingnamespace std;constint N =10010;bool tr[N];intmain(){int len, m;
cin >> len >> m;for(int i =0; i <= len; i++) tr[i]=true;int ans =0;while(m--){int l, r;
cin >> l >> r;for(int i = l; i <= r; i++) tr[i]=false;}for(int i =0; i <= len; i++)if(tr[i]) ans++;
cout << ans << endl;return0;}
区间合并
#include<iostream>#include<cstdio>#include<algorithm>usingnamespace std;constint N =10010;
pair<int,int> a[N];intmain(){int L, M;
cin >> L >> M;for(int i =0; i < M; i++) cin >> a[i].first >> a[i].second;sort(a, a + M);int cnt =0;int l = a[0].first, r = a[0].second;for(int i =1; i < M; i++){if(a[i].first >= r){
cnt += r - l +1;
l = a[i].first, r = a[i].second;}else{
r =max(r, a[i].second);}}
cnt += r - l +1;
cout << L +1- cnt << endl;return0;}
线段树解法
#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<cmath>#include<map>#include<vector>#include<functional>#include<algorithm>#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)#define ll long long#define int ll#define INF 0x3f3f3f3f#define PI acos(-1)#define MOD 1000000007#define mem(a, b) memset(a, b, sizeof a)#define print(n) printf("%lld\n", n)usingnamespace std;intread(){int w =1, s =0;char ch =getchar();while(ch <'0'|| ch>'9'){if(ch =='-') w =-1; ch =getchar();}while(ch >='0'&& ch <='9'){ s = s *10+ ch -'0';ch =getchar();}return s * w;}//最大公约数intgcd(int x,int y){if(x<y)swap(x,y);//很多人会遗忘,大数在前小数在后//递归终止条件千万不要漏了,辗转相除法return x % y ?gcd(y, x % y): y;}//计算x和y的最小公倍数intlcm(int x,int y){return x * y /gcd(x, y);//使用公式}intksm(int a,int b){int s =1;while(b){if(b&1) s=s*a%MOD;a=a*a%MOD;b>>=1;}return s;}intcmp(int x,int y){return x > y;}//int C(int n, int m) {// if (n < m) return 0;// return f[n] * ksm(f[m] * f[n - m] % MOD, MOD - 2) % MOD; //}//------------------------ 以上是我常用模板与刷题几乎无关 ------------------------//constint N =10010;struct node {int l, r;int sum;}tr[N <<2];//由子节点的信息来计算父节点的信息voidpushup(int cur){
tr[cur].sum = tr[cur <<1].sum + tr[cur <<1|1].sum;}//cur代表当前节点,voidbuild(int cur,int l,int r){//当前结点的左右儿子分别是tr[cur].l tr[cur].r
tr[cur]={l, r};//如果已经是叶结点returnif(l == r){
tr[cur].sum =1;return;}//否则求一下当前区间的中点int mid = l + r >>1;//递归建立左边区间build(cur <<1, l, mid);//递归建立右边区间build(cur <<1|1, mid +1, r);pushup(cur);}//cur代表当前线段树里面的端点。tar代表要修改的位置voidmodify(int cur,int l,int r,int x,int y){if(l > y || r < x || tr[cur].sum ==0)return;//如果当前节点就是叶节点,那么直接修改就可以了if(l >= x && r <= y){
tr[cur].sum =0;return;}int mid = l + r >>1;//递归两边modify(cur <<1, l, mid, x, y);modify(cur <<1|1, mid +1, r, x, y);//递归完之后,要更新到父节点。//pushup就是更新父节点的信息pushup(cur);}signedmain(){int L =read(), M =read();build(1,1, L +1);for(int i =0; i < M; i++){int x =read(), y =read();modify(1,1, L +1, x +1, y +1);}print(tr[1].sum);return0;}
422. 校门外的树暴力解法区间合并线段树解法暴力解法#include<iostream>#include<cstdio>using namespace std;const int N = 10010;bool tree[N];int main(){ int len, m; cin >> len >> m; for (int i = 0; i <= len; i++) tree[i] = true; in