luoguP5105 不强制在线的动态快速排序

 emm

可重集合没用用。直接变成不可重复集合

有若干个区间

每个区间形如[L,R]

[L,R]计算的话,就是若干个连续奇数的和。拆位统计1的个数

平衡树维护

加入一个[L,R],把相交的区间合并。之后相邻不相交的部分O(1)计算贡献到答案里。

O(nlogn+30n)

 不强制在线的动态快速排序

写起来并不太好写

set就可以

删除一些区间,合并成大区间

要分类讨论

至于calc(l,r)

有O(1)公式,可以不用按位:

第一个第二个发现了,后面就是多余位置处理即可。

代码:

1.注意插入区间被包含的情况,删掉前驱,R还要取一个max

2.按位的话,最高的是1e9+1e9=2e9,是1<<30,不是29.。。

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
int q;
struct po{
    ll l,r;
    po(){}
    po(int x,int y){
        l=x;r=y;
    }
    bool friend operator <(po a,po b){
        if(a.l!=b.l) return a.l<b.l;
        return a.r<b.r;
    }
};
set<po>s;
set<po>::iterator it,le,ri;
ll ans;
ll pre(int x,ll p){
    if(p==0) return x%2;
    if(p==1) {
        if(x%4==0) return 0;
        if(x%2==0) return 1;
        if(x%4==1) return 0;
        if(x%4==3) return 1;
    }
    x=x%(1<<p);
    if(x==0) return (1<<(p-1))%2;
    return max(0,x-(1<<(p-1)))%2;
}
ll clac(int l,int r){
    ll ret=0;
    l=(l+l+1)/2+1;
    r=(r+r-1)/2+1;
    if(l>r) return 0;
    for(ll i=30;i>=0;--i){
        ret+=(pre(r,i)-pre(l-1,i)+2+2+2)%2*(1<<i);
    }
    return ret;
}
void dele(int typ){

    if(typ==0){//pre and bac and me    
        ll tmp=clac((*it).l,(*it).r);
        ans^=tmp;
        ri=it;
        ++ri;
        if(ri!=s.end()){
            ans^=((*ri).l)*((*ri).l)-((*it).r)*((*it).r);
        }
        le=it;
        if(le!=s.begin()){
            --le;
            ans^=((*it).l)*((*it).l)-((*le).r)*((*le).r);
        }
        s.erase(it);
    }
    else if(typ==1){//bac and me
        ll tmp=clac((*it).l,(*it).r);
        ans^=tmp;
        ri=it;
        ++ri;
        if(ri!=s.end()){
            ans^=((*ri).l)*((*ri).l)-((*it).r)*((*it).r);
        }
        s.erase(it);
    }else {//only bac
        ri=it;
        ++ri;
        if(ri!=s.end()){
            ans^=((*ri).l)*((*ri).l)-((*it).r)*((*it).r);
        }
    }
}
void ins(int l,int r){
    if(s.empty()){
        ans^=clac(l,r);
        s.insert(po(l,r));
    }else{
        it=s.lower_bound(po(l,r));
        ll L=l,R=r;
        //bool fl=false;
        if(it!=s.begin()){
            --it;
            if((*it).r>=l-1){
                L=min(L,(*it).l);
                R=max(R,(*it).r);
                dele(0);
                //fl=true;
                it=s.lower_bound(po(l,r));
            }else{
                dele(2);
            }
        }
        while(1){
            it=s.lower_bound(po(l,r));
            if(it==s.end()) break;
            if((*it).l>r) break;
            R=max(R,(*it).r);
            dele(1);
        }
        
        if(it!=s.end()){
            ans^=((*it).l)*((*it).l)-R*R;
        }
        if(it!=s.begin()){
            --it;
            ans^=L*L-((*it).r)*((*it).r);
        }
        ans^=clac(L,R);
        s.insert(po(L,R));
    }
}
int main(){
    rd(q);
    int op,l,r;
    while(q--){
        rd(op);
        if(op==1){
            rd(l);rd(r);
            ins(l,r);
        }else{
            printf("%lld
",ans);
        }
    }
    return 0;
}

}
signed main(){
//    freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/1/16 9:17:43
*/
原文地址:https://www.cnblogs.com/Miracevin/p/10267818.html