8月8号的线段树:HDU 1754&&POJ 3264&&HDU1166
很明显,没有A一道题,题目意思很容易懂,但是就是shit的超时!!
之后就崩溃了。
晚上好像弄懂了线段树,先上题目:
要用线段树才不会超时:
(计算机运行数目达到10^8就要1S了!!而一般题目就是那么2000MS~5000MS)
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int a[200005]; 6 struct line 7 { 8 int left; 9 int right; 10 int max1; 11 }node[200005*20]; 12 void build(int left,int right,int root) 13 { 14 node[root].left=left; 15 node[root].right=right; 16 if(left==right) 17 { 18 node[root].max1=a[left]; 19 } 20 else 21 { 22 build(left,(left+right)/2,2*root); 23 build((left+right)/2+1,right,2*root+1); 24 node[root].max1=max(node[2*root].max1,node[2*root+1].max1); 25 } 26 } 27 int find1(int left1,int right1,int root) 28 { 29 if(node[root].left>right1||node[root].right<left1) 30 return 0; 31 if(left1<=node[root].left&&right1>=node[root].right) 32 return node[root].max1; 33 int a,b; 34 a=find1(left1,right1,2*root); 35 b=find1(left1,right1,2*root+1); 36 return max(a,b); 37 } 38 int update(int x,int y,int root) 39 { 40 if(x<node[root].left||x>node[root].right) 41 return 0; 42 if(node[root].left==x&&node[root].right==x) 43 return node[root].max1=y; 44 node[root].max1=max(update(x,y,2*root),update(x,y,2*root+1)); 45 return node[root].max1; 46 }//这里不仅把自己的值更新,而且把改变之后每个根节点的最大值也进行了更新! 47 int main() 48 { 49 int i,n,m,a1,a2; 50 char b[2]; 51 while(scanf("%d%d",&n,&m)!=EOF) 52 { 53 for(i=1;i<=n;i++) 54 scanf("%d",&a[i]); 55 build(1,n,1); 56 while(m--) 57 { 58 scanf("%s%d%d",b,&a1,&a2); 59 if(b[0]=='Q') 60 printf("%d\n",find1(a1,a2,1)); 61 else 62 { 63 a[a1]=a2; 64 update(a1,a2,1); 65 } 66 } 67 } 68 return 0; 69 }
第一次看懂:首先题目数据的默认顺序应该是1,2,3,4...(不然那个线段树怎么判断找哪个点到哪个点)
还有根节点,左节点,右节点的求法确定(即树的大体样子要清楚)
找东西的话(题目从线段数要求解的),得从根节点往下找起!
以根节点为依据,看他们的左右孩子和问题的关系。(包围还是半包围)
上面一个题的变行:这里不要update.
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int a[50005]; 6 int MaxNum,MinNum; 7 struct line 8 { 9 int left; 10 int right; 11 int max1; 12 int min1; 13 }node[50005*20]; 14 void build(int left,int right,int root) 15 { 16 node[root].left=left; 17 node[root].right=right; 18 if(left==right) 19 { 20 node[root].max1=a[left]; 21 node[root].min1=a[right]; 22 } 23 else 24 { 25 build(left,(left+right)/2,root*2); 26 build((left+right)/2+1,right,2*root+1); 27 node[root].max1=max(node[root*2].max1,node[root*2+1].max1); 28 node[root].min1=min(node[root*2].min1,node[root*2+1].min1); 29 } 30 } 31 int find1(int left1,int right1,int root) 32 { 33 if(left1>node[root].right||right1<node[root].left) 34 return 0; 35 if(left1<=node[root].left&&right1>=node[root].right) 36 { 37 MaxNum=max(node[root].max1,MaxNum); 38 MinNum=min(node[root].min1,MinNum); 39 return (MaxNum-MinNum); 40 } 41 int a,b; 42 a=find1(left1,right1,2*root); 43 b=find1(left1,right1,2*root+1); 44 return max(a,b); 45 } 46 int main() 47 { 48 int n,m,i,a1,a2; 49 while(scanf("%d%d",&n,&m)!=EOF) 50 { 51 for(i=1;i<=n;i++) 52 scanf("%d",&a[i]); 53 build(1,n,1); 54 while(m--) 55 { 56 scanf("%d%d",&a1,&a2); 57 MaxNum = -99999999; 58 MinNum = 99999999; 59 printf("%d\n",find1(a1,a2,1)); 60 } 61 } 62 return 0; 63 }
为什么上面的第一题不用开个MaxNum来求最大值,而后面的题目要开个MaxNum,MinNum来求最大值和最小值?
那是因为第一题只要求最大值,而第二题那最大值和最小值可能不在同一if判断语句中啊!!!!!
(貌似这个问题只有我才会犯的吧,主要是第二题的代码直接是第一题的克隆体,才会那么在意那些不同之处!)
敌兵布阵 HDU1166
加深对线段树的理解:(首先明确一旦建立好线段树,那么就不会有重叠和交叉)
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 int a[50005],ans; 6 struct line 7 { 8 int left; 9 int right; 10 int sum; 11 }node[50005*20]; 12 void build(int left,int right,int root) 13 { 14 node[root].left=left; 15 node[root].right=right; 16 if(left==right) 17 node[root].sum=a[left]; 18 else 19 { 20 build(left,(left+right)/2,2*root); 21 build((left+right)/2+1,right,2*root+1); 22 node[root].sum=node[root*2].sum+node[root*2+1].sum; 23 } 24 } 25 void query(int left1,int right1,int root) 26 { 27 if(left1>node[root].right||right1<node[root].left) 28 return ; 29 if(left1<=node[root].left&&right1>=node[root].right) 30 ans+=node[root].sum; 31 else 32 { 33 query(left1,right1,2*root); 34 query(left1,right1,2*root+1); 35 } 36 } 37 void insert1(int x,int y,int root) 38 { 39 if(x<node[root].left||x>node[root].right) 40 return ; 41 if(x>=node[root].left&&x<=node[root].right) 42 node[root].sum+=y; 43 insert1(x,y,2*root); 44 insert1(x,y,2*root+1); 45 } 46 int main() 47 { 48 int d=0,t,n,i,a1,a2; 49 char b[8]; 50 scanf("%d",&t); 51 while(t--) 52 { 53 scanf("%d",&n); 54 for(i=1;i<=n;i++) 55 scanf("%d",&a[i]); 56 build(1,n,1); 57 printf("Case %d:\n",++d); 58 while(scanf("%s",b)!=EOF) 59 { 60 if(b[0]=='E') 61 break; 62 scanf("%d%d",&a1,&a2); 63 if(b[0]=='Q') 64 { 65 ans=0; 66 query(a1,a2,1); 67 printf("%d\n",ans); 68 } 69 else if(b[0]=='A') 70 insert1(a1,a2,1); 71 else 72 insert1(a1,-a2,1); 73 } 74 } 75 return 0; 76 }