https://www.luogu.org/problemnew/show/P1047
第一次脱离模板写线段树题目(洛谷的线段树模板题太变态了)。言归正传,这是一个未完成版的线段树,因为一直到最后都没有发现为什么第一组数据会WA.后来苦心研究之后,发现线段树处理0的时候会有问题,于是想了两个解决办法应对该情况。
这个题目唯一的坑点在于从0开始,意思是输入的500实质上有501棵树,而线段树的结点和范围都必须从1开始,这也是做这题的教训吧。
解决办法1:将数组范围,修改左边界与修改右边界各加一,也就是输入范围为500时实质上建树时是501,修改范围输入100~200实际上查询101~201.
贴上代码:
#include<algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
typedef long long ll;
#define rep(i,a,n) for (int i = a; i < n; ++i)
#define per(i,a,n) for (int i = n-1; i >= a; --i)
#define SZ(x) ((int)x.size())
using namespace std;
//head
#define maxn 1000006
ll sx[maxn << 2];
inline ll ls(ll x) { return x << 1; }
inline ll rs(ll x) { return x << 1 | 1; }
inline void push_down(ll o, ll lc, ll rc);
inline void maintain(ll o)
{
sx[o] = sx[ls(o)] + sx[rs(o)];
}
void build(ll o, ll lc, ll rc)
{
if (lc == rc)
{
sx[o] = 1;
return;
}
ll m = (lc + rc) >> 1;
build(ls(o), lc, m);
build(rs(o), m + 1, rc);
maintain(o);
}
void update(ll o, ll lc, ll rc, ll ql, ll qr)
{
if (ql <= lc && qr >= rc)
{
sx[o] = 0;
push_down(o, lc, rc);
return;
}
ll m = (lc + rc) >> 1;
if (ql <= m) update(ls(o), lc, m, ql, qr);
if (qr > m) update(rs(o), m + 1, rc, ql, qr);
maintain(o);
}
inline void push_down(ll o, ll lc, ll rc)
{
if (lc == rc)
{
sx[o] = 0;
return;
}
ll m = (lc + rc) >> 1;
push_down(ls(o), lc, m);
push_down(rs(o), m + 1, rc);
maintain(o);
}
int main()
{
ll L, M;
scanf("%lld %lld", &L, &M);
L++;
build(1, 1, L);
while (M--)
{
ll a, b;
scanf("%lld %lld", &a, &b);
a++;
b++;
update(1, 1, L, a, b);
}
printf("%lld\n", sx[1]);
return 0;
}
解决办法2:
这个是朋友想出来的,用一个flag,如果碰到0则flag = 1,如果flag = 1则答案加1
这里还有个坑就是修改0~0时线段树会炸
贴上代码:
#include<algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
typedef long long ll;
#define rep(i,a,n) for (int i = a; i < n; ++i)
#define per(i,a,n) for (int i = n-1; i >= a; --i)
#define SZ(x) ((int)x.size())
using namespace std;
//head
#define maxn 1000006
ll sx[maxn << 2];
inline ll ls(ll x) { return x << 1; }
inline ll rs(ll x) { return x << 1 | 1; }
inline void push_down(ll o, ll lc, ll rc);
inline void maintain(ll o)
{
sx[o] = sx[ls(o)] + sx[rs(o)];
}
void build(ll o, ll lc, ll rc)
{
if (lc == rc)
{
sx[o] = 1;
return;
}
ll m = (lc + rc) >> 1;
build(ls(o), lc, m);
build(rs(o), m + 1, rc);
maintain(o);
}
void update(ll o, ll lc, ll rc, ll ql, ll qr)
{
if (ql <= lc && qr >= rc)
{
sx[o] = 0;
push_down(o, lc, rc);
return;
}
ll m = (lc + rc) >> 1;
if (ql <= m) update(ls(o), lc, m, ql, qr);
if (qr > m) update(rs(o), m + 1, rc, ql, qr);
maintain(o);
}
inline void push_down(ll o, ll lc, ll rc)
{
if (lc == rc)
{
sx[o] = 0;
return;
}
ll m = (lc + rc) >> 1;
push_down(ls(o), lc, m);
push_down(rs(o), m + 1, rc);
maintain(o);
}
int main()
{
ll L, M;
int flag = 0;
scanf("%lld %lld", &L, &M);
build(1, 1, L);
while (M--)
{
ll a, b;
scanf("%lld %lld", &a, &b);
if(a == 0 && b == 0)
{
flag = 1;
continue;
}
else if(a == 0)
flag = 1;
update(1, 1, L, a, b);
}
if(flag)
printf("%lld\n", sx[1]);
else
printf("%lld\n", sx[1] + 1);
return 0;
}