P5105 不强制在线的动态快速排序
$igoplus limits_{i=2}^n (a_i^2-a_{i-1}^2) = igoplus limits_{i=2}^n (a_i-a_{i-1})×(a_i+a_{i-1})$
关于$l~r$区间,由于$a_i=a_{i-1}+1$
$ igoplus limits_{i=l}^{r-1} (2i+1)=igoplus limits_{i=1}^{r-1} (2i+1)igoplus limits_{i=1}^{l-1} (2i+1)$
区间内奇数异或和,按位分解,其实只与$2^i$的个数有关
打表,可以发现$O(1)$的规律
设$n=4m+k$
当$k={0,1,2,3}$前缀和分别为${2n,3,2n+2,1}$
线段树维护区间异或和,修改$O(log_1e9)$查询$O(1)$
My complete code:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> using namespace std; typedef long long LL; inline LL Read(){ LL x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }return x*f; } const LL maxn=10000000; const LL inf=1e10; struct node{ LL mx,mi,son[2],sum,lazy; }tree[maxn]; LL nod,m,root; inline void Update(LL now){ LL l=tree[now].son[0],r=tree[now].son[1]; tree[now].mi=tree[l].mi?tree[l].mi:tree[r].mi; tree[now].mx=tree[r].mx?tree[r].mx:tree[l].mx; tree[now].sum=tree[l].sum^tree[r].sum; if(l&&r) tree[now].sum^=(tree[l].mx+tree[r].mi)*(tree[r].mi-tree[l].mx); if(tree[l].lazy&&tree[r].lazy) tree[now].lazy=1; } inline LL Get(LL x){ LL now=x%4; if(!now) return x<<1; if(now==1) return 3; if(now==2) return (x<<1)+2; return 1; } void Add(LL &now,LL l,LL r,LL lt,LL rt){ if(lt>r||rt<l||tree[now].lazy) return; if(!now) now=++nod; if(lt<=l&&rt>=r){ tree[now].mi=l, tree[now].mx=r, tree[now].sum=Get(l-1)^Get(r-1); tree[now].lazy=1; return; } LL mid=(l+r)>>1; Add(tree[now].son[0],l,mid,lt,rt); Add(tree[now].son[1],mid+1,r,lt,rt); Update(now); } int main(){ m=Read(); while(m--){ LL op=Read(),l,r; if(op==1) l=Read(),r=Read(), Add(root,1,1e9,l,r); else printf("%lld ",tree[root].sum); } return 0; }