题目传送门
首先提一下本题的几个容易忽略的坑点导致错误的地方吧
1.
问最终校门外留下的树苗多少棵?
是不是一开始看到时就不经过脑子的直接输出校门口的树的棵数啦(其实题目有说一开始就存在的是树,后面种下去的是树苗)(然后你就会获得80或者20分的好成绩),可能只有我一个人看错了吧
2.
植树者种上又被砍掉的树苗有多少棵?
这个可能错的人比较少,它的意思是每逢砍树者把树苗砍了就把ans++,并不是在一个树坑中只能ans++一次
3.
校门外马路上本来从编号0到L,每一编号的位置都有1棵树。
把编号看错的应该不止我一个人吧(试图自我安慰)
终上所述,审题一定要好好审,不然原来完全对的程序也会爆零(我才不会告诉你我为了找出这些坑点给洛谷提供了一页的提交记录呢)
再养成一个好习惯
做题前先看看一下数据的大小
这题的数据是
哎,O(n^2)的模拟好像可以*∗过去?
那来吧,写模拟(可以写模拟的就不要写线段树了嘛,线段树那个码量不敢恭维)
#include<bits/stdc++.h>
#define ll long long//随手long long好习惯
using namespace std;
const ll FFF=10000+5;
ll l,n;
bool opt;//判断是砍树还是种树
ll a,b;
ll flag[FFF];//flag=1时是树(就是一开始就存在的),flag=2时是树苗(就是后来种下的)
//flag=0时是空气(空坑)
ll ans_1,ans_2;//ans_1记录最终校门外留下的树苗棵数,ans_2记录植树者种上又被砍掉的树苗棵数
int main()
{
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
ios::sync_with_stdio(false);//关闭流同步,让cin、cout变得和scanf、printf一样快
cin>>l>>n;
for(int i=0;i<=l;++i)//记住编号从0开始,到l结束
{
flag[i]=1;//初始化,把树都种上
}
for(int i=0;i<n;++i)
{
cin>>opt>>a>>b;
if(opt==0)//如果是砍树
{
for(int j=a;j<=b;++j)//那就砍呗,从a到b
{
if(flag[j]==2)//如果砍的是树苗
{
ans_2+=1;//ans_2++
}
flag[j]=0;//让flag=0,即记为空坑
}
}
else//如果是种树
{
for(int j=a;j<=b;++j)
{
if(flag[j]==0)//如果遇到一个空坑
{
flag[j]=2;//就把树苗种上,把flag变为2(注意,是树苗了,不能把flag变成1)
}
}
}
}
for(int i=0;i<=l;++i)//最后处理
{
if(flag[i]==2)//如果校门口有树苗的话
{
ans_1+=1;//ans_1++
}
}
cout<<ans_1<<endl<<ans_2;//输出,完结撒花
return 0;
}
我的AC代码
#include <iostream>
#include <cstdio>
#define SIZE 100 + 10
#define SIZE2 (int)1e4 + 10
using namespace std;
int tree[SIZE2];
void print(const int *, const int &);
int main() {
freopen("cpp.in", "r", stdin);
freopen("cpp.out", "w", stdout);
int n, L, ans2 = 0, ans = 0;
scanf("%d%d", &L, &n);
for (int i = 1; i <= n; ++i) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
if (x == 0) {
for (int i = y; i <= z; ++i) {
if (tree[i] == 2) {
++ans2;
}
tree[i] = 1;
}
} else {
for (int i = y; i <= z; ++i) {
if (tree[i] == 1) {
tree[i] = 2;
}
}
}
}
for (int i = 0; i <= L; ++i) {
if (tree[i] == 2) {
++ans;
}
}
printf("%d\n%d\n", ans, ans2);
return 0;
}