hdu4614 线段树区间修改值,区间查询和

第一个二分查找的是第num个0,第二个二分查找的是最后一个0

把lrj大白书里的线段树重打一遍成以后模板,关于里面的maintain函数:

 1 #include
 2 #include<string.h>
 3 #include
 4 using namespace std;
 5 int n,ll;
 6 int setv[200005],sumv[200005];
 7 int query(int o,int l,int r,int y1,int y2)
 8 {
 9   if (setv[o]>=0) return setv[o]*(min(r,y2)-max(l,y1)+1);
10   else if (y1<=l&&y2>=r) return sumv[o];
11   else{
12     int mid=l+(r-l)/2,tmp=0;
13     if (y1<=mid) tmp+=query(o*2,l,mid,y1,y2);
14     if (y2>mid) tmp+=query(o*2+1,mid+1,r,y1,y2);
15     return tmp;
16   }
17 }
18 void maintain(int o,int l,int r)
19 {
20   sumv[o]=0;
21   if (setv[o]>=0) sumv[o]=setv[o]*(r-l+1);
22   else sumv[o]=sumv[o*2]+sumv[o*2+1];
23 }
24 void update(int o,int l,int r,int y1,int y2,int v)
25 {
26   int mid=l+(r-l)/2;
27   if (y1<=l&&y2>=r) setv[o]=v;
28   else{
29     if (setv[o]>=0){
30       setv[o*2]=setv[o*2+1]=setv[o];
31       setv[o]=-1;
32     }
33     if (y1<=mid) update(o*2,l,mid,y1,y2,v);
34     else maintain(o*2,l,mid);
35     if (y2>mid) update(o*2+1,mid+1,r,y1,y2,v);
36     else maintain(o*2+1,mid+1,r);
37   }
38   maintain(o,l,r);
39 }
40 int left_search(int l,int r,int num)
41 {
42   int mid=l+(r-l)/2;
43   if (l==r) return l;
44   int tmp=query(1,1,n,ll,mid);
45   if (tmp+num<=mid-ll+1) return left_search(l,mid,num);
46   return left_search(mid+1,r,num);
47 }
48 int right_search(int l,int r)
49 {
50   int mid=l+(r-l)/2+1;
51   if (l==r) return l;
52   int tmp=query(1,1,n,mid,n);
53   if (tmp+1<=n-mid+1) return right_search(mid,r);
54   return right_search(l,mid-1);
55 }
56 int main()
57 {
58   int T,m,k,x,y,tmp,tl,tr;
59   scanf("%d",&T);
60   while (T--)
61   {
62     scanf("%d%d",&n,&m);
63     memset(sumv,0,sizeof(sumv));
64     memset(setv,-1,sizeof(setv));
65     while (m--)
66     {
67       scanf("%d%d%d",&k,&x,&y);
68       if (k==2)
69       {
70         x++; y++;
71         tmp=query(1,1,n,x,y);
72         printf("%d\n",tmp);
73         update(1,1,n,x,y,0);
74       }
75       else{
76         x++;
77         tmp=query(1,1,n,x,n);
78         if (tmp==n-x+1) {
79           printf("Can not put any one.\n"); 
80           continue; 
81         }
82         ll=x;
83         if (n-x+1-tmpright_search(x,n);
84         else tr=left_search(x,n,y);
85         tl=left_search(x,n,1);
86         printf("%d %d\n",tl-1,tr-1);
87         update(1,1,n,tl,tr,1);
88       }
89     }
90     printf("\n");
91   }
92   return 0;
93 }
View Code

展开可以写成只用query和update函数:

 1 #include
 2 #include<string.h>
 3 #include
 4 using namespace std;
 5 int n,ll;
 6 int setv[200005],sumv[200005];
 7 int query(int o,int l,int r,int y1,int y2)
 8 {
 9   if (setv[o]>=0) return setv[o]*(min(r,y2)-max(l,y1)+1);
10   else if (y1<=l&&y2>=r) return sumv[o];
11   else{
12     int mid=l+(r-l)/2,tmp=0;
13     if (y1<=mid) tmp+=query(o*2,l,mid,y1,y2);
14     if (y2>mid) tmp+=query(o*2+1,mid+1,r,y1,y2);
15     return tmp;
16   }
17 }
18 void update(int o,int l,int r,int y1,int y2,int v)
19 {
20   int mid=l+(r-l)/2;
21   if (y1<=l&&y2>=r) setv[o]=v;
22   else{
23     if (setv[o]>=0){
24       setv[o*2]=setv[o*2+1]=setv[o];
25       setv[o]=-1;
26     }
27     if (y1<=mid) update(o*2,l,mid,y1,y2,v);
28     else if (setv[o*2]>=0) sumv[o*2]=setv[o*2]*(mid-l+1);
29     if (y2>mid) update(o*2+1,mid+1,r,y1,y2,v);
30     else if (setv[o*2+1]>=0) sumv[o*2+1]=setv[o*2+1]*(r-mid);
31   }
32   if (setv[o]>=0) sumv[o]=setv[o]*(r-l+1);
33   else sumv[o]=sumv[o*2]+sumv[o*2+1];
34 }
35 int left_search(int l,int r,int num)
36 {
37   int mid=l+(r-l)/2;
38   if (l==r) return l;
39   int tmp=query(1,1,n,ll,mid);
40   if (tmp+num<=mid-ll+1) return left_search(l,mid,num);
41   return left_search(mid+1,r,num);
42 }
43 int right_search(int l,int r)
44 {
45   int mid=l+(r-l)/2+1;
46   if (l==r) return l;
47   int tmp=query(1,1,n,mid,n);
48   if (tmp+1<=n-mid+1) return right_search(mid,r);
49   return right_search(l,mid-1);
50 }
51 int main()
52 {
53   int T,m,k,x,y,tmp,tl,tr;
54   scanf("%d",&T);
55   while (T--)
56   {
57     scanf("%d%d",&n,&m);
58     memset(sumv,0,sizeof(sumv));
59     memset(setv,-1,sizeof(setv));
60     while (m--)
61     {
62       scanf("%d%d%d",&k,&x,&y);
63       if (k==2)
64       {
65         x++; y++;
66         tmp=query(1,1,n,x,y);
67         printf("%d\n",tmp);
68         update(1,1,n,x,y,0);
69       }
70       else{
71         x++;
72         tmp=query(1,1,n,x,n);
73         if (tmp==n-x+1) {
74           printf("Can not put any one.\n"); 
75           continue; 
76         }
77         ll=x;
78         if (n-x+1-tmpright_search(x,n);
79         else tr=left_search(x,n,y);
80         tl=left_search(x,n,1);
81         printf("%d %d\n",tl-1,tr-1);
82         update(1,1,n,tl,tr,1);
83       }
84     }
85     printf("\n");
86   }
87   return 0;
88 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614

转载于:https://www.cnblogs.com/xiao-xin/articles/4198995.html

你可能感兴趣的:(hdu4614 线段树区间修改值,区间查询和)