서브 간격으로 2019icpc 난창 (南昌) 네트워크 게임 _I_Yukino

문제의 의미

두 작업 원 포인트 수정 쿼리 간격의 시퀀스 주어 \ ([L, R] \ ) 의 범위 (\ [X, Y] \ ) 의 범위에서 연속적인 세그먼트의 수.

분석

  • 같은 광원 어레이 \ (A \) 는 새로운 배열 구조 (B \) \를 \을 (B [I] = (A [I] == A [-I. 1]) 0 :? A [I] \) 왼쪽 끝 지점에 연속 섹션이 표시됩니다, 그래서 숫자.
  • 문의는 보호로 전환시킬 수있다 \ (b의 \) 가중치 트리 트리 라인의 집합의 배열과, 배열 문의 단일 지점과 값 범위의 다수의 섹션 수를 수정.
  • 차이의 개념과 유사하게 요구할 \ (L, R의 \) 우리 쿼리 할 것은 \ (b \) 배열 ([L + 1, R] \) \ , 따라서 놓치지 A [L] (\ \) 이 상기 논의 점에 최종 판정 \ (a [1] \) 조건 범위를 만족하는 경우에는 그 여부 \ (a [L + 1] \) 와 동일하다 (a [1]을 \) \ 답 해야 플러스 1.
  • 미터 C ++ 11 캔 34xx의 오프 마늘 \ (MS \) 카드도 C ++ (14)는 T. 될 것입니다
  • 트리 나무 과학 슬리브 ... T 축적한다 겉보기 응답의 방법을 사용하여 개별적으로 계산 그러한 기록 노드 활성 상태를 고려하는 방법이며

코드

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+150;
int n,m,a[N],b[N];
int o,l,r,xi,yi;
int x[N],y[N];
int c1,c2;
int tr[N*150];
struct HJT{
#define mid (l+r)/2
    int tot,sum[N*150],ls[N*150],rs[N*150];
    void update(int& rt,int l,int r,int v,int add){
        //因为b数组有0值,在查询时0不算
        if(!v){
            return;
        }
        if(!rt){
            rt=++tot;
        }
        sum[rt]+=add;
        if(l<r){
            if(v<=mid){
                update(ls[rt],l,mid,v,add);
            }else{
                update(rs[rt],mid+1,r,v,add);
            }
        }
    }
    //区间[l,r]值域在[1,k]的个数
    int query(int l,int r,int k){
        if(k==0){
            return 0;
        }
        if(r<=k){
            int ans=0;
            for(int i=1;i<=c1;i++){
                ans-=sum[x[i]];
            }
            for(int i=1;i<=c2;i++){
                ans+=sum[y[i]];
            }
            return ans;
        }
        if(k<=mid){
            for(int i=1;i<=c1;i++){
                x[i]=ls[x[i]];
            }
            for(int i=1;i<=c2;i++){
                y[i]=ls[y[i]];
            }
            return query(l,mid,k);
        }else{
            int ans=0;
            for(int i=1;i<=c1;i++){
                ans-=sum[ls[x[i]]];
            }
            for(int i=1;i<=c2;i++){
                ans+=sum[ls[y[i]]];
            }
            for(int i=1;i<=c1;i++){
                x[i]=rs[x[i]];
            }
            for(int i=1;i<=c2;i++){
                y[i]=rs[y[i]];
            }
            return ans+query(mid+1,r,k);
        }
    }
}ac;
struct BIT{
    int lowbit(int x){
        return x&(-x);
    }
    //修改权值线段树的bit前缀和(非连续)
    void modify(int i,int x){
        int k=b[i];
        while(i<=n){
            ac.update(tr[i],1,n,k,x);
            i+=lowbit(i);
        }
    }
    //预处理权值线段树的查询路径
    int query(int l,int r,int xi,int yi){
        c1=c2=0;
        for(int i=(l-1);i;i-=lowbit(i)){
            x[++c1]=tr[i];
        }
        for(int i=r;i;i-=lowbit(i)){
            y[++c2]=tr[i];
        }
        int R=ac.query(1,n,yi);
        c1=c2=0;
        for(int i=(l-1);i;i-=lowbit(i)){
            x[++c1]=tr[i];
        }
        for(int i=r;i;i-=lowbit(i)){
            y[++c2]=tr[i];
        }
        int L=ac.query(1,n,xi-1);
        return R-L;
    }
}bit;
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        b[i]=(a[i]==a[i-1])?0:a[i];
    }
    for(int i=1;i<=n;i++){
        bit.modify(i,1);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&o,&l,&r);
        if(o==1){
            bit.modify(l,-1);
            bit.modify(l+1,-1);
            a[l]=r;
            b[l]=(a[l]==a[l-1])?0:a[l];
            b[l+1]=(a[l+1]==a[l])?0:a[l+1];
            bit.modify(l,1);
            bit.modify(l+1,1);
        }else{
            scanf("%d%d",&xi,&yi);
            int ans=bit.query(l+1,r,xi,yi);
            if(a[l]>=xi && a[l]<=yi){
                ans++;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

추천

출처www.cnblogs.com/zxcoder/p/11496897.html