题解 P1276 【校门外的树(增强版)】

chen_zhe

2017-05-28 20:13:56

Solution

这道题是可以用线段树做的,不过有点闲的没事干 ```cpp #include <iostream> #include <cstdio> using namespace std; struct Seg_Tree { int left,right,value;//value表示:2为树苗 1为树木 0为没有树 -1为不能当做整体 可以省略一个标记 }son[150000]; int l,n,ans1=0,ans2=0; void Build(int id,int left,int right) //没什么好说的建树 { son[id].left=left; son[id].right=right; son[id].value=1; if (left==right) return; Build(id<<1,left,(left+right)>>1); Build(id<<1|1,((left+right)>>1)+1,right); } void Update_Cut(int id,int left,int right) //砍树 { int mid=(son[id].left+son[id].right)>>1; //计算分段的位置 if (son[id].value!=1 && son[id].value!=-1) son[id<<1].value=son[id<<1|1].value=son[id].value; //继承 if (left==son[id].left && right==son[id].right) {//此处代码可以优化到更短 if (son[id].value==0) return; //没有树可以不砍 if (son[id].value==1) son[id].value=0; //有树木直接砍掉 if (son[id].value==2) { son[id].value=0; //树苗也要砍 ans1+=(son[id].right-son[id].left)+1; //计算种上被砍掉的树苗 ans2=ans2-(son[id].right-son[id].left+1); //计算留下的树苗 } if (son[id].value==-1) //不能一起做就交给自己的左儿子和右儿子做 { son[id].value=0; Update_Cut(id<<1,left,(left+right)>>1); Update_Cut(id<<1|1,((left+right)>>1)+1,right); } } else { if (right<=mid) Update_Cut(id<<1,left,right); else if (left>mid) Update_Cut(id<<1|1,left,right); else { Update_Cut(id<<1,left,mid); Update_Cut(id<<1|1,mid+1,right); } //“三部曲”往下推 if (son[id<<1].value!=son[id<<1|1].value) son[id].value=-1; else son[id].value=son[id<<1].value; //判断左右儿子是否相等,确定是否要整体一起做 } } void Update_Plant(int id,int left,int right) { int mid=(son[id].left+son[id].right)>>1; if (son[id].value!=1 && son[id].value!=-1) son[id<<1].value=son[id<<1|1].value=son[id].value; //同上 if (left==son[id].left && right==son[id].right) { if (son[id].value==1 || son[id].value==2) return; //树木不要种! if (son[id].value==0) { son[id].value=2; ans2+=(son[id].right-son[id].left)+1; //计算树苗的个数 } if (son[id].value==-1) //防止下面有树木,所以不要在这里做son[id].value=2 { Update_Plant(id<<1,left,(left+right)>>1); Update_Plant(id<<1|1,((left+right)>>1)+1,right); } } else { if (right<=mid) Update_Plant(id<<1,left,right); else if (left>mid) Update_Plant(id<<1|1,left,right); else { Update_Plant(id<<1,left,mid); Update_Plant(id<<1|1,mid+1,right); } if (son[id<<1].value!=son[id<<1|1].value) son[id].value=-1; else son[id].value=son[id<<1].value; //同上 } } int main() { scanf("%d%d",&l,&n); Build(1,0,l); for (int i=1;i<=n;i++) { int c,a,b; scanf("%d%d%d",&c,&a,&b); if (a>b) swap(a,b); //防止a>b if (c==0) Update_Cut(1,a,b); else Update_Plant(1,a,b); } printf("%d\n%d\n",ans2,ans1); return 0; } ```