这个是我做的线段树第三个题,比前两个区间求和稍微麻烦了一些!
大致意思是:
给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。
这题我用了两种方法,说是两种,其实就中间的某些细节不太一样!
Nuumber one:
每个线段树的结点,存储该结点所代表区间的染色状况num,如果该区间全为同样的颜色,则用一个正数(1,2,3)表示,如果含有多种颜色,则用-1表示,每次执行染色操作时,如果所要染的颜色与区间颜色一样,则停止,如果所要染区间跟当前结点区间一致,则直接将所要染颜色赋给当前结点的num,否则,如果当前结点区间不是混合色,则先将当前结点的颜色赋给左右子结点的num,并递归下去。
# include<stdio.h> # define N 400000 struct node{ int left,right,mid; int num; }a[N]; int val; void make(int s,int t,int step) { a[step].num=1; a[step].left=s; a[step].right=t; a[step].mid=(s+t)/2; if(s==t) return; make(s,a[step].mid,2*step); make(a[step].mid+1,t,2*step+1); } void change(int ans1,int ans2,int step) { if(a[step].num==val) return; if(a[step].left==ans1 && a[step].right==ans2 ) {a[step].num=val;return;} if(a[step].num!=-1) {a[step*2].num=a[step*2+1].num=a[step].num;} a[step].num=-1; if(ans1>a[step].mid) change(ans1,ans2,2*step+1); else if(ans2<=a[step].mid) change(ans1,ans2,2*step); else { change(ans1,a[step].mid,2*step); change(a[step].mid+1,ans2,2*step+1); } } int count(int step) { if(a[step].num>0) return (a[step].right-a[step].left+1)*a[step].num; return count(step*2)+count(2*step+1); } int main() { int ncase=0,n,m,t,ans1,ans2; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); make(1,n,1); while(m--) { scanf("%d%d%d",&ans1,&ans2,&val); change(ans1,ans2,1); } printf("Case %d: The total value of the hook is %d.\n",++ncase,count(1)); } return 0; }
Number two:
成段更新,总区间求和!
# include<stdio.h> # define N 400000 struct node{ int left,right,mid; int num,value; }a[N]; int val; void make(int s,int t,int step) { a[step].left=s; a[step].right=t; a[step].mid=(s+t)/2; a[step].num=t-s+1; a[step].value=1; if(s==t) return; make(s,a[step].mid,2*step); make(a[step].mid+1,t,2*step+1); } void change(int ans1,int ans2,int step) { if(a[step].value==val) return; if(ans1==a[step].left && a[step].right==ans2) { a[step].value=val; a[step].num=(a[step].right-a[step].left+1)*a[step].value; return; } if(a[step].value>0) { a[step*2].value=a[step].value; a[step*2].num=(a[step*2].right-a[step*2].left+1)*a[step*2].value; a[step*2+1].value=a[step].value; a[step*2+1].num=(a[step*2+1].right-a[step*2+1].left+1)*a[step*2+1].value; a[step].value=0; } if(ans1>a[step].mid) change(ans1,ans2,2*step+1); else if(ans2<=a[step].mid) change(ans1,ans2,2*step); else { change(ans1,a[step].mid,2*step); change(a[step].mid+1,ans2,2*step+1); } a[step].num=a[2*step].num+a[2*step+1].num; } int main() { int ncase=0,n,m,t,ans1,ans2; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); make(1,n,1); while(m--) { scanf("%d%d%d",&ans1,&ans2,&val); change(ans1,ans2,1); } printf("Case %d: The total value of the hook is %d.\n",++ncase,a[1].num); } return 0; }