hdu1540 区间合并模板(点修改及查询)

传送门::http://acm.hdu.edu.cn/showproblem.php?pid=1540

题意:有n个连在一起的地道,接下来m个操作,D x 代表摧毁 x 地道;R 代表修建最近一次摧毁的地道;R x 查询与x地道相连的地道有多少个(最大连续区间长度)

 思路::线段树

线段树区间合并问题,维护三个变量

llen ::从左端点开始的最大连续区间长度

rlen::从右端点开始的最大连续区间长度

mlen::该区间的最大连续长度

如何维护呢?

双亲的llen 如果它左孩子的整个区间连续,llen=左孩子llen+右孩子的llen

双亲的rlen 如何它右孩子的整个区间来连续,rlen=右孩子rlen+左孩子的rlen

双亲的mlen  左孩子的mlen,右孩子的mlen,左孩子的rlen+右孩子的llen 三者最大值

至于查询的话也比较简单

   如果它在左孩子rlen中,结果就是左孩子derlen+右孩子的llen,反之就在左孩子里

  如果他在右孩子的llen中,结果就是右孩子的llen+左孩子的rllen反之就在右孩子里

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int maxn=5e4+5;
 5 
 6 int llen[maxn<<2],rlen[maxn<<2],mlen[maxn<<2];
 7 
 8 stack<int>s;
 9 
10 void pushup(int rt,int m)
11 {
12     mlen[rt]=max(max(mlen[2*rt],mlen[2*rt+1]),rlen[2*rt]+llen[2*rt+1]);
13     llen[rt]=llen[2*rt];
14     rlen[rt]=rlen[2*rt+1];
15     if(llen[2*rt]==m-(m>>1))
16         llen[rt]+=llen[2*rt+1];
17     if(rlen[2*rt+1]==(m>>1))
18         rlen[rt]+=rlen[2*rt];
19 }
20 void build(int l,int r,int rt)
21 {
22     llen[rt]=rlen[rt]=mlen[rt]=r-l+1;
23     if(l==r){return ;}
24     int mid=(l+r)>>1;
25     build(l,mid,2*rt);
26     build(mid+1,r,2*rt+1);
27 }
28 void update(int l,int r,int rt,int pos,int k)
29 {
30     if(l==r){
31         llen[rt]=rlen[rt]=mlen[rt]=k;
32         return ;
33     }
34     int mid=(l+r)>>1;
35     if(pos<=mid)
36         update(l,mid,2*rt,pos,k);
37     else
38         update(mid+1,r,2*rt+1,pos,k);
39     pushup(rt,r-l+1);
40 }
41 int query(int l,int r,int rt,int pos)
42 {
43     if(mlen[rt]==0||mlen[rt]==(r-l+1)){
44         return mlen[rt];
45     }
46     int mid=(l+r)>>1;
47     if(pos<=mid){
48         if(pos>=mid-rlen[2*rt]+1)
49             return rlen[2*rt]+llen[2*rt+1];
50         else
51             return query(l,mid,2*rt,pos);
52     }
53     else{
54         if(pos<=mid+llen[2*rt+1])
55             return llen[2*rt+1]+rlen[2*rt];
56         else
57             return query(mid+1,r,2*rt+1,pos);
58     }
59 }
60 int main()
61 {
62     int n,m;
63     while(~scanf("%d%d",&n,&m)){
64     build(1,n,1);
65     while(m--)
66     {
67         char op;int k;
68         scanf(" %c",&op);
69         if(op=='R'&&!s.empty()){
70             update(1,n,1,s.top(),1);
71             s.pop();
72         }
73         else if(op=='D'){
74             scanf("%d",&k);
75             s.push(k);
76             update(1,n,1,k,0);
77         }
78         else {
79             scanf("%d",&k);
80             printf("%d
",query(1,n,1,k));
81         }
82     }
83     }
84     return 0;
85 }
纵使单枪匹马,也要勇闯天涯
原文地址:https://www.cnblogs.com/sj-gank/p/11842625.html