2018年湖南省省赛 H题-千万不要用树套树

不要被题目给误导,这题根本不用树套树(我也不会),用线段树就可以完美解决。。。

比赛时也想到用线段树,但是想的太简单了,于是连wa两发。。然后一直到比赛结束也没有

想到正确思路,说到底我的线段树还是太菜了啊,感觉这题对线段树水平的要求比我的水平高了

两个等级,许老师的线段树水平比我高了至少三个等级,所以没费多大力就想到了正确思路。。

赛后许老师提醒了我几个关键点,发现这题只要构思好了其实并不是很难啊。,唉。。上代码:

#include
#include
#include
#include
using namespace std;
int sumv1[400005],sumv2[400005],cnt[400005];
int T,n,q,c,p,ql,qr,p1,ql1,qr1,x,y;
void update1(int o,int l,int r){
    int m=(l+r)/2;
    if(l==r)sumv1[o]+=1;
    else{
        if(p<=m)update1(o*2,l,m);
        else update1(o*2+1,m+1,r);
        sumv1[o]=sumv1[o*2]+sumv1[o*2+1];
    }
}
int query1(int o,int l,int r){
    int m=(l+r)/2;
    if(l>=ql&&r<=qr)return sumv1[o];
    int ans=0;
    if(ql<=m)ans+=query1(o*2,l,m);
    if(qr>m)ans+=query1(o*2+1,m+1,r);
    return ans;
}
void update2(int o,int l,int r){
    int m=(l+r)/2;
    if(l==r)sumv2[o]+=1;
    else{
        if(p1<=m)update2(o*2,l,m);
        else update2(o*2+1,m+1,r);
        sumv2[o]=sumv2[o*2]+sumv2[o*2+1];
    }
}
int query2(int o,int l,int r){
    int m=(l+r)/2;
    if(l>=ql1&&r<=qr1)return sumv2[o];
    int ans=0;
    if(ql1<=m)ans+=query2(o*2,l,m);
    if(qr1>m)ans+=query2(o*2+1,m+1,r);
    return ans;
}
int main(){
    while(~scanf("%d%d",&n,&q)){
        for(int i=0;i<=n*4;i++){
            sumv1[i]=sumv2[i]=cnt[i]=0;
        }
        int s=0;
        while(q--){
            scanf("%d",&c);
            if(c==1){
                scanf("%d%d",&p,&p1);
                if(p==p1)cnt[p]++;
                update1(1,1,n);
                update2(1,1,n);
                s++;
            }
            else{
                scanf("%d%d",&x,&y);
                ql=x+1,qr=n;
                ql1=1,qr1=y-1;
                int ans=s;
                if(qr>=ql)ans-=query1(1,1,n);
                if(qr1>=ql1)ans-=query2(1,1,n);
                if(y-x==2)ans+=cnt[x+1];
                printf("%d\n",ans);
            }
        }
    }    
}

 

你可能感兴趣的:(2018年湖南省省赛 H题-千万不要用树套树)