hdu 1540

写的时候一直没发现有一个问题

看了一遍kuangbin的代码,自己以为理解了,手写了一边,wa了

找了半天才发现   Query(o<<1|1,mid+1,r,mid+1) 不是Query(o<<1|1,mid+1,r) 位置是x

 

我选择x的话,会一直递归左子树 答案就是变成2了

实际答案是3

第一份代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50005;
int n,m,x,v;
int sum[maxn*4],lsum[maxn*4],rsum[maxn*4];
int a[maxn];
int dq[maxn];
void Build(int o,int l,int r)
{
    sum[o]=lsum[o]=rsum[o]=r-l+1;
    if(l==r) {
        return ;
    }
    int mid=l+r>>1;
    Build(o<<1,l,mid);
    Build(o<<1|1,mid+1,r);
}
void Update(int o,int l,int r)
{
    if(l==r) {
       lsum[o]=rsum[o]=sum[o]=v; return ;
    }
    int mid=l+r>>1;
    if(x<=mid) {
        Update(o<<1,l,mid);
    }
    else{
        Update(o<<1|1,mid+1,r);
    }
    lsum[o]=lsum[o<<1];
    rsum[o]=rsum[o<<1|1];
    sum[o]=max(sum[o<<1],max(sum[o<<1|1],rsum[o<<1]+lsum[o<<1|1]));
    if(lsum[o<<1]==mid-l+1) {
        lsum[o]+=lsum[o<<1|1];
    }
    if(rsum[o<<1|1]==r-mid) {
        rsum[o]+=rsum[o<<1];
    }
}
int  Query(int o,int l,int r,int x)
{
    if(l==r||sum[o]==r-l+1||sum[o]==0) {
        return sum[o];
    }
    int mid=l+r>>1;
    if(x<=mid) {
        if(x>=mid-rsum[o<<1]+1) {
            return Query(o<<1,l,mid,x)+Query(o<<1|1,mid+1,r,mid+1);
        }
        else {
              return Query(o<<1,l,mid,x);
        }
    }
    else{
        if(x<=mid+lsum[o<<1|1]) {
            return Query(o<<1,l,mid,mid)+Query(o<<1|1,mid+1,r,x);
        }
        else{
             return Query(o<<1|1,mid+1,r,x);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        Build(1,1,n);
        char s[5];
        int len=0;
        while(m--) {
            scanf("%s",s);
            if(s[0]=='D') {
                scanf("%d",&x); v=0;
                Update(1,1,n); dq[len++]=x;
    //            printf("%d %d %d\n",sum[1],lsum[1],rsum[1]);
            }
            if(s[0]=='Q') {
                scanf("%d",&x);
                printf("%d\n",Query(1,1,n,x));
            }
            if(s[0]=='R') {
                x=dq[--len]; v=1;
                Update(1,1,n);
            }
        }
    }
}

我自己又感觉麻烦,改了改那一点,代码如下

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=50005;
int n,m,x,v;
int sum[maxn*4],lsum[maxn*4],rsum[maxn*4];
int a[maxn];
int dq[maxn];
void Build(int o,int l,int r)
{
    sum[o]=lsum[o]=rsum[o]=r-l+1;
    if(l==r) {
        return ;
    }
    int mid=l+r>>1;
    Build(o<<1,l,mid);
    Build(o<<1|1,mid+1,r);
}
void Update(int o,int l,int r)
{
    if(l==r) {
       lsum[o]=rsum[o]=sum[o]=v; return ;
    }
    int mid=l+r>>1;
    if(x<=mid) {
        Update(o<<1,l,mid);
    }
    else{
        Update(o<<1|1,mid+1,r);
    }
    lsum[o]=lsum[o<<1];
    rsum[o]=rsum[o<<1|1];
    sum[o]=max(sum[o<<1],max(sum[o<<1|1],rsum[o<<1]+lsum[o<<1|1]));
    if(lsum[o<<1]==mid-l+1) {
        lsum[o]+=lsum[o<<1|1];
    }
    if(rsum[o<<1|1]==r-mid) {
        rsum[o]+=rsum[o<<1];
    }
}
int  Query(int o,int l,int r,int x)
{
    if(l==r||sum[o]==r-l+1||sum[o]==0) {
        return sum[o];
    }
    int mid=l+r>>1;
    if(x<=mid) {
        if(x>=mid-rsum[o<<1]+1) {
            return rsum[o<<1]+lsum[o<<1|1];
        }
        else {
              return Query(o<<1,l,mid,x);
        }
    }
    else{
        if(x<=mid+lsum[o<<1|1]) {
            return rsum[o<<1]+lsum[o<<1|1];
        }
        else{
             return Query(o<<1|1,mid+1,r,x);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        Build(1,1,n);
        char s[5];
        int len=0;
        while(m--) {
            scanf("%s",s);
            if(s[0]=='D') {
                scanf("%d",&x); v=0;
                Update(1,1,n); dq[len++]=x;
    //            printf("%d %d %d\n",sum[1],lsum[1],rsum[1]);
            }
            if(s[0]=='Q') {
                scanf("%d",&x);
                printf("%d\n",Query(1,1,n,x));
            }
            if(s[0]=='R') {
                x=dq[--len]; v=1;
                Update(1,1,n);
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值