E - Tunnel Warfare HDU - 1540

E - Tunnel Warfare HDU - 1540

区间合并+单点修改,查询最大连续长度

区间修改的线段树实现起来稍微比较麻烦,因为维护两个区间左右延伸的数组。

每次查询的时候,如果该区间是sum[rt]||l==r||sum[rt]==r-l+1,那么返回,否则继续向下查找,因为是单点修改,每次修改都要到最底层,所以懒标记不起作用,其他的就是代码实现的问题了。

  1 #include <iostream>
  2 #include <stack>
  3 #include <algorithm>
  4 #define lson l,m,rt<<1
  5 #define rson m+1,r,rt<<1|1
  6 using namespace std;
  7 
  8 const int maxn=5e4+5;
  9 int sum[maxn<<3],lsum[maxn<<3],rsum[maxn<<3];
 10 
 11 //建树 
 12 void build(int l,int r,int rt){
 13     if(l==r)
 14     {
 15         sum[rt]=lsum[rt]=rsum[rt]=1;
 16         return ;
 17     } 
 18     sum[rt]=lsum[rt]=rsum[rt]=r-l+1;
 19     int m=(l+r)>>1;
 20     build(lson);
 21     build(rson);
 22 }
 23 
 24 void pushup(int rt,int len){
 25     lsum[rt]=lsum[rt<<1];
 26     rsum[rt]=rsum[rt<<1|1];
 27     if(lsum[rt]==len-(len>>1)) lsum[rt]+=lsum[rt<<1|1];
 28     /*if(rt==2)
 29         cout <<"rt="<<rt<<" "<<(len<<1)<<endl;*/
 30     if(rsum[rt]==len>>1) rsum[rt]+=rsum[rt<<1];
 31     sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
 32 }
 33 
 34 //更新 
 35 void update(int p,int x,int l,int r,int rt){
 36     if(p==l&&p==r){
 37         if(x==0){
 38             sum[rt]=lsum[rt]=rsum[rt]=0;
 39         }else
 40             sum[rt]=lsum[rt]=rsum[rt]=1;
 41         //cout << "genshi"<<rt<<" "<<p<<endl;
 42         return;
 43     }
 44     int m=(l+r)>>1;
 45     if(p<=m) update(p,x,lson);
 46         else update(p,x,rson);
 47     pushup(rt,r-l+1);
 48 }
 49  
 50 //查询
 51 int query(int p,int l,int r,int rt){
 52     if(sum[rt]==r-l+1||l==r||sum[rt]==0){
 53         return sum[rt];
 54     }
 55     int m=(l+r)>>1;
 56     if(p<=m)
 57     {
 58         if(p>=m-rsum[rt<<1]+1) return query(p,lson)+query(m+1,rson);
 59             else return query(p,lson);
 60     }
 61     else{
 62         if(p<=m+lsum[rt<<1|1]) return query(p,rson)+query(m,lson);
 63             else return query(p,rson);
 64     } 
 65 } 
 66 
 67 
 68 
 69 
 70 int main(){
 71     int n,m;
 72     std::ios::sync_with_stdio(false);
 73     while(cin>>n>>m)
 74     {
 75         
 76     
 77     build(1,n,1);
 78             /*for(int i=1;i<=20;i++)
 79             {
 80                 cout << i<<" "<<sum[i]<<endl;        
 81             }    */    
 82     //cout <<"*****************\n";
 83     stack <int> S;
 84     char c[3];
 85     while(m--){
 86         cin>>c;
 87         if(c[0]=='D') {
 88             int x;cin>>x;
 89             S.push(x);
 90             update(x,0,1,n,1);
 91         /*    for(int i=1;i<=20;i++)
 92             {
 93                 cout << i<<" "<<sum[i]<<" "<<lsum[i]<<" "<<rsum[i]<<endl;        
 94             }        */
 95         }else if(c[0]=='R'){
 96             int x;x=S.top();
 97             //cout <<x<<endl;
 98             update(x,1,1,n,1);
 99             S.pop();
100             /*for(int i=1;i<=20;i++)
101             {
102                 cout << i<<" "<<sum[i]<<endl;        
103             }    */    
104         }else{    
105             int x;cin>>x;
106             cout <<query(x,1,n,1)<<"\n";
107         }    
108     }
109 }
110     return 0;
111 }

 

转载于:https://www.cnblogs.com/Msmw/p/11281339.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值