[Luogu5105]不强制在线的动态快速排序
首先集合去重不影响答案,然后打表易得连续自然数平方差异或前缀和的规律,于是问题就变为在线维护区间求并同时更新答案,set记录所有区间,每次暴力插入删除即可。由于每个区间至多只会插入删除一次,故均摊复杂度$O(n\log n)$
1 #include<set> 2 #include<cstdio> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 typedef long long ll; 6 using namespace std; 7 8 const int N=300010; 9 int Q,op,l,r; 10 ll ans; 11 struct P{ int l,r; }; 12 bool operator <(const P &a,const P &b){ return a.l<b.l; } 13 set<P>S; 14 15 ll D(int n){ 16 n=(n+1)/2; 17 if (n%4==1) return 2*n-1; 18 if (n%4==2) return 2; 19 if (n%4==3) return 2*n+1; 20 return 0; 21 } 22 23 ll calc(int l,int r){ if (l==r) return 0; else return D(r*2-1)^D(l*2-1); } 24 25 ll get(set<P>::iterator it){ 26 int l=it->l,r=it->r,u=-1,v=-1; ll res=calc(l,r); 27 it++; if (it!=S.end()) res^=1ll*((it->l)+r)*((it->l)-r),u=it->l; 28 it--; if (it!=S.begin()) it--,res^=1ll*(l+(it->r))*(l-(it->r)),v=it->r; 29 if (~u && ~v) res^=1ll*(u+v)*(u-v); 30 return res; 31 } 32 33 void work(int l,int r){ 34 if (S.empty()) { ans=calc(l,r); S.insert((P){l,r}); return; } 35 set<P>::iterator it=S.lower_bound((P){l,r}); 36 while (it!=S.end() && it->l<=r) 37 l=min(l,it->l),r=max(r,it->r),ans^=get(it),S.erase(it),it=S.lower_bound((P){l,r}); 38 if (it!=S.begin()){ 39 it--; 40 while (it->r>=l){ 41 l=min(l,it->l); r=max(r,it->r); ans^=get(it); S.erase(it); 42 it=S.lower_bound((P){l,r}); 43 if (it==S.begin()) break; else it--; 44 } 45 } 46 it=S.insert((P){l,r}).first; ans^=get(it); 47 //for (it=S.begin(); it!=S.end(); it++) printf("%d %d\n",it->l,it->r); puts(""); 48 } 49 50 int main(){ 51 for (scanf("%d",&Q); Q--; ){ 52 scanf("%d",&op); 53 if (op==1) scanf("%d%d",&l,&r),work(l,r); else printf("%lld\n",ans); 54 } 55 return 0; 56 }