Codeforces - 331B2 权值线段树 区间合并

题意:题目太玄了我无法用语言精简..

题目要求的操作1是基于值的,所以用普通线段树基本无法维护(反正我不知道)
换做权值型后十分好做,因为连接处必然是更后面的,这时比较一下位置就好
PS.感觉周赛越来越硬核了

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
using namespace std;
const int MAXN = 3e5+11;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int a[MAXN],pos[MAXN];
ll read(){
    ll x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct ST{
    #define lc o<<1
    #define rc o<<1|1
    int cnt[MAXN<<2];
    void pu(int o,int l,int r){
        cnt[o]=cnt[lc]+cnt[rc];
        int taillc=l+r>>1;
        int headrc=taillc+1;
        if(pos[taillc]<pos[headrc]) cnt[o]--;
    }
    void build(int o,int l,int r){
        if(l==r){
            cnt[o]=1;
            return;
        }
        int mid=l+r>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
        pu(o,l,r);
    }
    ll query(int o,int l,int r,int L,int R){
        if(L<=l&&r<=R){
            return cnt[o];
        }
        int mid=l+r>>1;
        ll ans1=0,ans2=0,ans3=0; 
        if(L<=mid) ans1=query(lc,l,mid,L,R);
        if(R>mid) ans2=query(rc,mid+1,r,L,R);
        if(ans1&&ans2){
            int taillc=l+r>>1;
            int headrc=taillc+1;
            if(pos[taillc]<pos[headrc]) ans3=-1;
        }
        return ans1+ans2+ans3;
    }
    void update(int o,int l,int r,int k,int v=1){
        if(l==r){
            return;
        }
        int mid=l+r>>1;
        if(k<=mid) update(lc,l,mid,k,v);
        else update(rc,mid+1,r,k,v);
        pu(o,l,r);
    }
}st;
int main(){
    int n,m;
    while(cin>>n){
        rep(i,1,n){
            a[i]=read();
            pos[a[i]]=i;
        }
        st.build(1,1,n);
        m=read();
        rep(i,1,m){
            int x,y,z;
            x=read();y=read();z=read();
            if(x==1){
                println(st.query(1,1,n,y,z));
            }else{
                int yy=a[y],zz=a[z];
                swap(pos[yy],pos[zz]);
                swap(a[y],a[z]);
                st.update(1,1,n,yy,1);
                st.update(1,1,n,zz,1);
            }
        }
    }
    return 0;
}
posted @ 2018-06-02 23:06  Caturra  阅读(217)  评论(0编辑  收藏  举报