线段树+区间合并学习记录

学习了线段树的新姿势,记录一下。

参考blog:https://blog.csdn.net/sunyutian1998/article/details/79618316

HDU 1540:

query的时候m-ql+1和qr-m写成了m-l+1、r-m,wa了几发之后才找到bug。

错误样例:

10 1
Q 5

wrong answer:5

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=5e4+5;
  4 struct node
  5 {
  6     int ll,rr,mm;
  7 } tr[4*maxn];
  8 #define lson o*2
  9 #define rson o*2+1
 10 #define m (l+r)/2
 11 inline void pushup(int o,int l,int r)
 12 {
 13     tr[o].ll=tr[lson].ll;
 14     tr[o].rr=tr[rson].rr;
 15     if(tr[o].ll==m-l+1)
 16         tr[o].ll+=tr[rson].ll;
 17     if(tr[o].rr==r-m)
 18         tr[o].rr+=tr[lson].rr;
 19     tr[o].mm=max(tr[lson].rr+tr[rson].ll,max(tr[lson].mm,tr[rson].mm));
 20 }
 21 void build(int o,int l,int r)
 22 {
 23     if(l==r)
 24     {
 25         tr[o].ll=tr[o].rr=tr[o].mm=1;
 26         return;
 27     }
 28     build(lson,l,m);
 29     build(rson,m+1,r);
 30     pushup(o,l,r);
 31 }
 32 void update(int o,int l,int r,int k,int flag)
 33 {
 34     if(l==r)
 35     {
 36         tr[o].ll=tr[o].rr=tr[o].mm=flag;
 37         return;
 38     }
 39     if(k<=m) update(lson,l,m,k,flag);
 40     else update(rson,m+1,r,k,flag);
 41     pushup(o,l,r);
 42 }
 43 int query(int o,int l,int r,int ql,int qr,int flag)
 44 {
 45     if(ql<=l&&qr>=r)
 46     {
 47         if(flag==1) return tr[o].ll;
 48         else return tr[o].rr;
 49     }
 50     if(qr<=m) return query(lson,l,m,ql,qr,flag);
 51     if(ql>m) return query(rson,m+1,r,ql,qr,flag);
 52     else
 53     {
 54         int pl=query(lson,l,m,ql,qr,flag);
 55         int pr=query(rson,m+1,r,ql,qr,flag);
 56         if(flag==1)
 57         {
 58             if(pl==m-ql+1) return pl+pr;
 59             else return pl;
 60         }
 61         else
 62         {
 63             if(pr==qr-m) return pl+pr;
 64             else return pr;
 65         }
 66     }
 67 }
 68 int a[maxn];
 69 int main()
 70 {
 71     int n,q;
 72     while(scanf("%d%d",&n,&q)!=EOF)
 73     {
 74         memset(a,0,sizeof a);
 75         build(1,1,n);
 76         int tp=0;
 77         while(q--)
 78         {
 79             char s;
 80             getchar();
 81             scanf("%c",&s);
 82             if(s=='D')
 83             {
 84                 int x;
 85                 scanf("%d",&x);
 86                 update(1,1,n,x,0);
 87                 a[++tp]=x;
 88             }
 89             if(s=='Q')
 90             {
 91                 int x;
 92                 scanf("%d",&x);
 93                 int x1=query(1,1,n,1,x,2);
 94                 int x2=query(1,1,n,x,n,1);
 95                 printf("%d\n",x1+x2>0?x1+x2-1:0);
 96             }
 97             if(s=='R')
 98             {
 99                 if(tp>=1)
100                 {
101                     int x=a[tp--];
102                     update(1,1,n,x,1);
103                 }
104             }
105         }
106     }
107 }
108 /*
109 10 1
110 Q 5
111 */
View Code

 

顺带一提,这个题目可以在set上面二分直接过,代码如下:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[50005];
 4 int main()
 5 {
 6     int n,q;
 7     while(~scanf("%d%d",&n,&q))
 8     {
 9         set<int>st;
10         st.insert(0);
11         int tp=0;
12         while(q--)
13         {
14             char c;
15             getchar();
16             scanf("%c",&c);
17             if(c=='D')
18             {
19                 int x;
20                 scanf("%d",&x);
21                 st.insert(x);
22                 a[++tp]=x;
23             }
24             if(c=='Q')
25             {
26                 int x;
27                 scanf("%d",&x);
28                 set<int>::iterator iter=st.lower_bound(x);
29                 if(iter==st.end())
30                 {
31                     iter--;
32                     printf("%d\n",n-*iter);
33                 }
34                 else
35                 {
36                     if(*iter==x) puts("0");
37                     else
38                     {
39                         int tmp=*iter;
40                         iter--;
41                         printf("%d\n",tmp-*iter-1);
42                     }
43                 }
44             }
45             if(c=='R')
46             {
47                 if(tp>=1)
48                 {
49                     int x=a[tp--];
50                     st.erase(x);
51                 }
52             }
53         }
54     }
55 }
View Code

 

HDU 4553:

维护两棵线段树,一棵是空闲时间,一棵是无视基友的空闲时,然后按区间合并的套路做就好了。

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=100005;
  4 struct node
  5 {
  6     int ll,rr,mm;
  7     int tag;
  8 }ans0[4*maxn],ans1[4*maxn];
  9 #define lson o*2
 10 #define rson o*2+1
 11 #define m (l+r)/2
 12 inline bool full(node tr[],int o,int l,int r)
 13 {
 14     return tr[o].mm==r-l+1;
 15 }
 16 inline void pushup(node tr[],int o,int l,int r)
 17 {
 18     tr[o].ll=tr[lson].ll;
 19     tr[o].rr=tr[rson].rr;
 20     if(tr[o].ll==m-l+1)
 21         tr[o].ll+=tr[rson].ll;
 22     if(tr[o].rr==r-m)
 23         tr[o].rr+=tr[lson].rr;
 24     tr[o].mm=max(tr[lson].rr+tr[rson].ll,max(tr[lson].mm,tr[rson].mm));
 25 }
 26 inline void pushdown(node tr[],int o,int l,int r)
 27 {
 28     if(full(tr,o,l,r))
 29     {
 30         tr[lson].ll=tr[lson].rr=tr[lson].mm=m-l+1;
 31         tr[rson].ll=tr[rson].rr=tr[rson].mm=r-m;
 32     }
 33     if(tr[o].mm==0)
 34     {
 35         tr[lson].ll=tr[lson].rr=tr[lson].mm=0;
 36         tr[rson].ll=tr[rson].rr=tr[rson].mm=0;
 37     }
 38 }
 39 void build(node tr[],int o,int l,int r)
 40 {
 41     tr[o].tag=-1;
 42     if(l==r)
 43     {
 44         tr[o].ll=tr[o].rr=tr[o].mm=1;
 45         return;
 46     }
 47     build(tr,lson,l,m);
 48     build(tr,rson,m+1,r);
 49     pushup(tr,o,l,r);
 50 }
 51 void update(node tr[],int o,int l,int r,int ql,int qr,int flag)
 52 {
 53     if(ql<=l&&qr>=r)
 54     {
 55         tr[o].ll=tr[o].rr=tr[o].mm=flag*(r-l+1);
 56         return;
 57     }
 58     pushdown(tr,o,l,r);
 59     if(qr<=m)
 60         update(tr,lson,l,m,ql,qr,flag);
 61     else if(ql>m)
 62         update(tr,rson,m+1,r,ql,qr,flag);
 63     else
 64     {
 65         update(tr,lson,l,m,ql,qr,flag);
 66         update(tr,rson,m+1,r,ql,qr,flag);
 67     }
 68     pushup(tr,o,l,r);
 69 }
 70 int query(node tr[],int o,int l,int r,int len)
 71 {
 72     if(tr[o].mm<len)
 73         return -1;
 74     pushdown(tr,o,l,r);
 75     if(full(tr,o,l,r))
 76         return l;
 77     if(tr[lson].mm>=len)
 78         return query(tr,lson,l,m,len);
 79     if(tr[lson].rr>0&&tr[lson].rr+tr[rson].ll>=len)
 80         return m-tr[lson].rr+1;
 81     if(tr[rson].mm>=len)
 82         return query(tr,rson,m+1,r,len);
 83 }
 84 int main()
 85 {
 86     int t;
 87     //freopen("in//in_t.txt","r",stdin);
 88     //freopen("in//myout.txt","w",stdout);
 89     scanf("%d",&t);
 90     int cas=1;
 91     while(t--)
 92     {
 93         printf("Case %d:\n",cas++);
 94         int n,q;
 95         scanf("%d%d",&n,&q);
 96         build(ans0,1,1,n);
 97         build(ans1,1,1,n);
 98         while(q--)
 99         {
100             char s[10];
101             scanf("%s",s);
102             if(s[0]=='D')
103             {
104                 int x;
105                 scanf("%d",&x);
106                 int pos=query(ans0,1,1,n,x);
107                 if(pos==-1) puts("fly with yourself");
108                 else
109                 {
110                     printf("%d",pos);
111                     puts(",let's fly");
112                     update(ans0,1,1,n,pos,pos+x-1,0);
113                 }
114             }
115             if(s[0]=='N')
116             {
117                 int x;
118                 scanf("%d",&x);
119                 int pos=query(ans0,1,1,n,x);
120                 if(pos==-1)
121                 {
122                     pos=query(ans1,1,1,n,x);
123                     if(pos==-1) puts("wait for me");
124                     else
125                     {
126                         printf("%d",pos);
127                         puts(",don't put my gezi");
128                         update(ans0,1,1,n,pos,pos+x-1,0);
129                         update(ans1,1,1,n,pos,pos+x-1,0);
130                     }
131                 }
132                 else
133                 {
134                     printf("%d",pos);
135                     puts(",don't put my gezi");
136                     update(ans0,1,1,n,pos,pos+x-1,0);
137                     update(ans1,1,1,n,pos,pos+x-1,0);
138                 }
139             }
140             if(s[0]=='S')
141             {
142                 int l,r;
143                 scanf("%d%d",&l,&r);
144                 puts("I am the hope of chinese chengxuyuan!!");
145                 update(ans0,1,1,n,l,r,1);
146                 update(ans1,1,1,n,l,r,1);
147             }
148         }
149     }
150 }
View Code

 

UVALive - 3938:

好像是道经典的线段树维护区间合并的题目。

动态查询区间连续最大和,输出那个最大和子区间的区间左端点和右端点,如果有多个子区间答案,输出l,r字典序最小的那一组。

线段树维护区间最大前缀和,后缀和,记录最大前缀和的结尾位置,最大后缀和的起点位置,以及最大子区间和的区间左右端点,至于区间求和,用前缀和sum[r]-sum[l-1]就好了。区间合并方式比较复杂,还是看代码吧:

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define LL long long
  4 const LL maxn=500005;
  5 typedef pair<LL,LL> P;
  6 struct node
  7 {
  8     LL ll,rr;
  9     P mxsub;
 10     LL pre,post;
 11     LL sum;
 12 }tr[4*maxn];
 13 LL pre_sum[maxn];
 14 inline LL calc(LL l,LL r)
 15 {
 16     return pre_sum[r]-pre_sum[l-1];
 17 }
 18 inline void comb(node& o,node& l,node& r)
 19 {
 20     o.sum=l.sum+r.sum;
 21     if(l.ll>=l.sum+r.ll)
 22     {
 23         o.ll=l.ll;
 24         o.pre=l.pre;
 25     }
 26     else
 27     {
 28         o.ll=l.sum+r.ll;
 29         o.pre=r.pre;
 30     }
 31     if(r.rr>r.sum+l.rr)
 32     {
 33         o.rr=r.rr;
 34         o.post=r.post;
 35     }
 36     else
 37     {
 38         o.rr=r.sum+l.rr;
 39         o.post=l.post;
 40     }
 41     LL tmp1=calc(l.mxsub.first,l.mxsub.second);
 42     LL tmp2=calc(r.mxsub.first,r.mxsub.second);
 43     if(tmp1>=tmp2)
 44     {
 45         o.mxsub=l.mxsub;
 46         if(tmp1<l.rr+r.ll)
 47         {
 48             o.mxsub.first=l.post;
 49             o.mxsub.second=r.pre;
 50         }
 51     }
 52     else
 53     {
 54         o.mxsub=r.mxsub;
 55         if(tmp2<=l.rr+r.ll)
 56         {
 57             o.mxsub.first=l.post;
 58             o.mxsub.second=r.pre;
 59         }
 60     }
 61 }
 62 LL a[maxn];
 63 #define lson o*2
 64 #define rson o*2+1
 65 #define m (l+r)/2
 66 void build(LL o,LL l,LL r)
 67 {
 68     if(l==r)
 69     {
 70         tr[o].ll=tr[o].rr=tr[o].sum=a[l];
 71         tr[o].pre=tr[o].post=tr[o].mxsub.first=tr[o].mxsub.second=l;
 72         return;
 73     }
 74     build(lson,l,m);
 75     build(rson,m+1,r);
 76     comb(tr[o],tr[lson],tr[rson]);
 77 }
 78 node query(LL o,LL l,LL r,LL ql,LL qr)
 79 {
 80     if(ql<=l&&qr>=r)
 81         return tr[o];
 82     if(qr<=m) return query(lson,l,m,ql,qr);
 83     if(ql>m) return query(rson,m+1,r,ql,qr);
 84     node tmp1=query(lson,l,m,ql,qr);
 85     node tmp2=query(rson,m+1,r,ql,qr);
 86     node ret;
 87     comb(ret,tmp1,tmp2);
 88     return ret;
 89 }
 90 int main()
 91 {
 92     LL n;
 93     LL cas=0;
 94     while(~scanf("%lld",&n))
 95     {
 96         printf("Case %lld:\n",++cas);
 97         LL q;
 98         scanf("%lld",&q);
 99         for(LL i=1;i<=n;i++)
100         {
101             scanf("%lld",a+i);
102             pre_sum[i]=pre_sum[i-1]+a[i];
103         }
104         build(1,1,n);
105         while(q--)
106         {
107             LL l,r;
108             scanf("%lld%lld",&l,&r);
109             node ans=query(1,1,n,l,r);
110             printf("%lld %lld\n",ans.mxsub.first,ans.mxsub.second);
111         }
112     }
113 }
View Code

 

posted @ 2018-11-19 14:20  Amori  阅读(258)  评论(0编辑  收藏  举报