本蒟蒻重學線段樹,發現了這道題可以用線段樹做。
雖然資料範圍很小可以直接暴力,但由於在練習線段樹所以打算用線段樹寫這道題。
本題解針對已經有線段樹基礎的巨佬,不懂線段樹原理的話可以學習線段樹後再閱讀本題解。
剛看題的時候以為大概是個線段樹模板,結果發現事情並不簡單。
題目要求的不是剩下多少棵樹和砍掉了多少棵樹木,而是要求剩下和砍掉了多少棵樹苗。
並且需要注意區間是從0開始的。
那麼注意到這些差不多就可以開始想做法了。
因為種樹人每次種樹種植的都是樹苗,所以只有最初的區間上會有一整個區間的樹木。所以我們可以對於樹木建立一棵線段樹,再對於樹木和樹苗共同建立一棵線段樹。這樣在砍樹的時候分別查詢兩棵線段樹並且進行差分,就可以得到區間上砍掉的樹苗的數量。最後查詢整個區間上樹苗個數同理
其中線段樹需要支援的操作
那麼具體實現**如下:
#includeusing namespace std;
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
#define ll long long
#define n 10010
int n,m;
struct node_tree
;struct tree//為了方便維護兩棵線段樹,於是開了結構體
build(i<<1,l,t[i].mid);
build(i<<1|1,t[i].mid+1,r);
t[i].d=(t[i<<1].d+t[i<<1|1].d);
return;
} void pushdown(int i)
void modify_vol(int i,int l,int r,int k)//區間賦值
pushdown(i);
if(l<=t[i].mid) modify_vol(i<<1,l,r,k);
if(t[i].mid+1<=r) modify_vol(i<<1|1,l,r,k);
t[i].d=(t[i<<1].d+t[i<<1|1].d);
return;
} int query(int i,int l,int r)//查詢區間和
pushdown(i);
int res=0;
if(l<=t[i].mid) res+=query(i<<1,l,r);
if(t[i].mid+1<=r) res+=query(i<<1|1,l,r);
return res;
} }t1,t2;//t1存樹木 t2存樹苗加樹木
int ans1,ans2;
int main()
if(opt)
/*這個是線段樹除錯(可以忽略)
for(int i=0;i<=n;++i)
putchar('\n');
*/} ans1=t2.query(1,0,n)-t1.query(1,0,n);
printf("%d\n%d",ans1,ans2);
return 0;
}
P1276 校門外的樹(增強版)
原題鏈結 考察 線段樹 or 模擬 模擬是很簡單啦,主要考慮線段樹怎麼寫,本題的線段樹比較特殊.思路 基本是參考了大佬的題解.本題的懶標記過於特殊把我寫懵了.操作 0 砍掉 l,r 區間的樹與樹苗 操作 1 種植 l,r 區間的樹苗.抽象到線段樹操作就是 0 l,r 區間 樹陣列 1,樹苗陣列 1....
洛谷 P1276 校門外的樹(增強版)
貌似很久以前 也就幾個星期幾個月前吧 看到過這題,但並沒有做還是懶,今天做一下也算是遲到的練習吧 祝我明天機房測試成功 題目裡還是藏著很多玄機的 1.樹和樹苗有什麼區別?答 沒有區別 樹是原來有的,而樹苗是閒的沒事幹的植樹者植的 因為生長需要時間嘛 2.注意是留下的樹苗 開始沒看見結果調了好久的錯 ...
luogu1276 校門外的樹(增強版)
時空限制 1000ms 128mb 校門外馬路上本來從編號0到l,每一編號的位置都有1棵樹。有砍樹者每次從編號a到b處連續砍掉每1棵樹,就連樹苗也不放過 記 0 a b 含a和b 幸運的是還有植樹者每次從編號c到d 中凡是空穴 樹被砍且還沒種上樹苗或樹苗又被砍掉 的地方都補種上樹苗 記 1 c d,...