#线段树#洛谷 5105 不强制在线的动态快速排序

题目链接


分析

这道题用可持久化权值线段树做,记录存在的最左边的数,最右边的数,对于连续的一段区间是可以打表找到答案的,如果不连续按照题目求,对于重复的区间,需要打标记,表示已经计算过了,就不需要再计算了


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
const int N=1e7+5;
int lazy[N],lef[N],rig[N],ls[N],rs[N],cnt,rt; long long w[N];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
void print(long long ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
inline signed calc(int x){
    return x&1?((x&3)==1?3:1):(x<<1)+(x&3);
}
inline void update(int &rt,int l,int r,int x,int y){
    if (lazy[rt]) return;
    if (!rt) rt=++cnt;
    if (l==x&&r==y){
        lef[rt]=x,rig[rt]=y,lazy[rt]=1;
        w[rt]=calc(y-1)^calc(x-1); return;
    }
    rr int mid=(l+r)>>1;
    if (y<=mid) update(ls[rt],l,mid,x,y);
    else if (x>mid) update(rs[rt],mid+1,r,x,y);
    else update(ls[rt],l,mid,x,mid),update(rs[rt],mid+1,r,mid+1,y);
    if (lef[ls[rt]]) lef[rt]=lef[ls[rt]]; else lef[rt]=lef[rs[rt]];
    if (rig[rs[rt]]) rig[rt]=rig[rs[rt]]; else rig[rt]=rig[ls[rt]];
    w[rt]=w[ls[rt]]^w[rs[rt]];
    if (lef[rs[rt]]&&rig[ls[rt]]) w[rt]^=1ll*(lef[rs[rt]]+rig[ls[rt]])*(lef[rs[rt]]-rig[ls[rt]]);
    if (lazy[ls[rt]]&&lazy[rs[rt]]) lazy[rt]=1;
}
signed main(){
    for (rr int t=iut();t;--t){
        rr int q=iut(),x,y;
        if (q&1) x=iut(),y=iut(),update(rt,1,1e9,x,y);
           else print(w[1]),putchar(10);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值