【線段樹】Just a Hook
阿新 • • 發佈:2019-01-01
區間更新,總區間求和
分析:
看到題目首先想到了線段樹,(因為題目是區間更新)區間更新需要用到延遲標記(或者說懶惰標記),簡單來說就是每次更新的時候不要更新到底,用延遲標記使得更新延遲到下次需要更新or詢問到的時候。延遲標記的意思是:這個區間的左右兒子都需要被更新,但是當前區間已經更新了。
節點中儲存的值代表這個區間的金屬成色(1-銅,2-銀,3-金;/如果這個區間還有其它成色,即雜色金屬,則值為-1。
原創程式碼
#include<string> #include<cstdio> #include<cstring> using namespace std; #define maxn 100000 int sum,n,m,x,y,z; struct node{ int l,r,w; }ac[maxn*4+1];//線段樹佔空間約為結點個數的 4 倍! void build(int k,int l,int r) { ac[k].l=l; ac[k].r=r; ac[k].w=1; if(l==r){ return ; } int mid=(ac[k].l+ac[k].r)/2; build(k*2,l,mid); build(k*2+1,mid+1,r); } //區間更新 void up(int k,int l,int r,int v) { if(ac[k].l==l && ac[k].r==r) { ac[k].w=v; return ; } if(ac[k].w==v) return ; if(ac[k].w!=-1)//編號為k的區間都為純色 { //下面附上顏色值 ac[2*k].w=ac[2*k+1].w=ac[k].w; ac[k].w=-1; } int mid=(ac[k].l+ac[k].r)/2; if(mid>=r) { up(k*2,l,r,v); } else if(mid<l) { up(k*2+1,l,r,v); } else{ up(k*2,l,mid,v); up(k*2+1,mid+1,r,v); } } int query(int k,int l,int r){ if(ac[k].w==-1) return query(k*2,l,r)+query(k*2+1,l,r); else return (ac[k].r-ac[k].l+1)*ac[k].w;//編號k都是純色 } int main(){ while(scanf("%d",&sum)!=EOF){ for(int s=1;s<=sum;s++){ scanf("%d%d",&n,&m); build(1,1,n); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); up(1,x,y,z); } printf("Case %d: The total value of the hook is %d.\n",s,query(1,1,n)); } } return 0; }