題解 P1276 校門外的樹(增強版)

2022-09-23 21:27:26 字數 1603 閱讀 9691

本蒟蒻重學線段樹,發現了這道題可以用線段樹做。

雖然資料範圍很小可以直接暴力,但由於在練習線段樹所以打算用線段樹寫這道題。

本題解針對已經有線段樹基礎的巨佬,不懂線段樹原理的話可以學習線段樹後再閱讀本題解。

剛看題的時候以為大概是個線段樹模板,結果發現事情並不簡單。

題目要求的不是剩下多少棵樹和砍掉了多少棵樹木,而是要求剩下和砍掉了多少棵樹苗

並且需要注意區間是從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,...