Limitの线段树题单加训

文章提供了一个使用C++编写的线段树数据结构,用于处理区间XOR操作的动态更新和查询问题。代码中定义了`info`结构体来存储区间统计信息,并实现了加法运算符重载以支持合并操作。同时,还定义了一个`node`结构体来维护线段树节点,包括区间和单点修改以及查询功能。
摘要由CSDN通过智能技术生成

XOR on Segment

#include<bits/stdc++.h>
#define endl '\n'

using namespace std;
typedef long long ll;

const int N = 1e5 + 100;

int n,q;
int a[N];

void fileio()
{
  //#ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  //#endif
}

struct info {
    int cnt[2][22] = {0};
    void init()
    {
        for(int i = 0;i < 2;i ++) for(int j = 0;j < 21;j ++) cnt[i][j] = 0;
    }
    void debug()
    {
        for(int i = 0;i < 2;i ++){ for(int j = 0;j < 21;j ++) cout << cnt[i][j] << ' '; cout << endl;}
    }
    ll cacl()
    {   
        ll tmp = 0;  
        for(int i = 0;i <= 20;i ++) if(cnt[1][i]) tmp += 1ll*(1<<i)*1ll*cnt[1][i]; 
        return tmp;
    } 
};

info operator + (const info &l,const info &r)
{
    info tmp; tmp.init();
    for(int i = 0;i <= 20;i ++) for(int j = 0;j < 2;j ++)
    tmp.cnt[j][i] = l.cnt[j][i] + r.cnt[j][i];
    return tmp;
}

info operator + (const info & v,ll t)
{
    info tmp; tmp.init();
    for(int i = 0;i <= 20;i ++) 
    if(t>>i&1) tmp.cnt[0][i] = v.cnt[1][i], tmp.cnt[1][i] = v.cnt[0][i];
    else tmp.cnt[0][i] = v.cnt[0][i], tmp.cnt[1][i] = v.cnt[1][i];
    return tmp;
}

struct node {
    ll t = 0ll; info val;
}seg[N * 4];

void update(int u){
    seg[u].val = seg[u<<1].val+seg[u<<1|1].val;
}

void settag(int u,ll t)
{
    seg[u].t = seg[u].t ^ t;
    seg[u].val = seg[u].val + t;
}

void pushdown(int u)
{
    if(seg[u].t != 0)
    {
        settag(u<<1, seg[u].t),settag(u<<1|1, seg[u].t);
        seg[u].t = 0;
    }
}

void build(int u,int l,int r)
{
    if(l == r){
        seg[u].val.init();
        for(int i = 0;i <= 20;i ++) seg[u].val.cnt[(a[l]>>i&1) ? 1 : 0][i] ++;
        return;
    }
    int mid = l+r>>1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    update(u);
}

void modify(int u,int l,int r,int ql,int qr,ll t)
{
    if(l == ql && r == qr){
        settag(u,t);return;
    }
    int mid = l+r>>1;
    pushdown(u);
    if(qr <= mid) modify(u<<1,l,mid,ql,qr,t);
    else if(ql > mid) modify(u<<1|1,mid+1,r,ql,qr,t);
    else modify(u<<1,l,mid,ql,mid,t),modify(u<<1|1,mid+1,r,mid+1,qr,t);
    update(u);
}

info query(int u,int l,int r,int ql,int qr)
{
    if(l == ql && r == qr) return seg[u].val;
    int mid = l+r>>1; 
    
    pushdown(u);
    
    if(qr <= mid) return query(u<<1,l,mid,ql,qr);
    if(ql > mid)  return query(u<<1|1,mid+1,r,ql,qr);
    return query(u<<1,l,mid,ql,mid)+query(u<<1|1,mid+1,r,mid+1,qr);
}

int main()
{
    ios::sync_with_stdio(false);
	cin.tie(0);
    //fileio();

    cin >> n;
    for(int i = 1;i <= n;i ++) cin >> a[i];

    build(1,1,n);

    cin >> q;
    for(int i = 0;i < q;i ++)
    {
        int opt; cin >> opt;
        if(opt == 1)
        {
            int l,r; cin >> l >> r;
            cout << query(1,1,n,l,r).cacl()<< endl;
        }
        else
        {
            int l,r; ll t; cin >> l >> r >> t;
            modify(1,1,n,l,r,t);
        }
    }

    //seg[1].val.debug();
   //cout <<  seg[1].val.cacl() << endl;
}

DZY Loves Fibonacci Numbers

这下面的代码 re了,不知道为啥

#include<bits/stdc++.h>
//#define int long long
#define endl '\n'

using namespace std;
typedef long long ll;

void fileio()
{
  //#ifdef LGS
  freopen("in.txt","r",stdin);
  freopen("out.txt","w",stdout);
  //#endif
}


const int N = 3e5 + 100;
const int mod = 1e9 + 9;

int n,m;
int a[N];

int fib[N]; int pre[N]; int rfib[N];
// fib[i] i  rfib[i] -i 
void init()
{
    fib[1] = fib[2] = pre[1] = rfib[1] = 1;
    fib[0] = rfib[0] = 0; pre[2]=2; rfib[2]=mod-1;
    for(int i = 3;i <= n+1;i ++)
    {
        fib[i] = (fib[i-1]+fib[i-2])%mod;
        pre[i] = (pre[i-1]+fib[i])%mod;
        rfib[i]=(i&1)?fib[i]:mod-fib[i];
    }
}

struct node {
    int sum = 0;
    int addx = 0;int addy = 0;
}seg[N * 4];

void update(int u){
    seg[u].sum = (seg[u<<1].sum+seg[u<<1|1].sum)%mod;
}

void settag(int u,int addx,int addy,int l,int r)
{
    seg[u].addx = (seg[u].addx + addx)%mod;
    seg[u].addy = (seg[u].addy + addy)%mod; 
    
    seg[u].sum=(seg[u].sum+1ll*(pre[r+1]-pre[l]+mod)%mod*seg[u].addx %mod)%mod;
    seg[u].sum=(seg[u].sum+1ll*(pre[r]-pre[l-1]+mod)%mod*seg[u].addy %mod)%mod;
}

void pushdown(int u,int l,int r)
{
    if(seg[u].addx == 0 && seg[u].addy == 0) return;
    
    int mid = l+r>>1;
    settag(u<<1, seg[u].addx,seg[u].addy,l,mid);
    settag(u<<1|1, seg[u].addx,seg[u].addy,mid+1,r);
    seg[u].addx = seg[u].addy = 0;
    
}

void build(int u,int l,int r)
{
    if(l == r){
        seg[u].sum = a[l]%mod;
        return;
    }
    int mid = l+r>>1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    update(u);
}

void modify(int u,int l,int r,int ql,int qr,int addx,int addy)
{
    if(l == ql && r == qr){
        settag(u,addx,addy,l,r);return;
    }
    int mid = l+r>>1;
    pushdown(u,l,r);
    if(qr <= mid) modify(u<<1,l,mid,ql,qr,addx,addy);
    else if(ql > mid) modify(u<<1|1,mid+1,r,ql,qr,addx,addy);
    else modify(u<<1,l,mid,ql,mid,addx,addy),modify(u<<1|1,mid+1,r,mid+1,qr,addx,addy);
    update(u);
}

int query(int u,int l,int r,int ql,int qr)
{
    if(l == ql && r == qr) return seg[u].sum%mod;
    int mid = l+r>>1; 
    
    pushdown(u,l,r);
    
    if(qr <= mid) return query(u<<1,l,mid,ql,qr) %mod;
    if(ql > mid)  return query(u<<1|1,mid+1,r,ql,qr) %mod;
    return query(u<<1,l,mid,ql,mid)+query(u<<1|1,mid+1,r,mid+1,qr) %mod;
}

void solve()
{
    cin >> n >> m;
    for(int i = 1;i <= n;i ++) cin >> a[i]; 
    
    init();

    build(1,1,n);

    for(int i = 0;i < m;i ++)
    {
        int opt; cin >> opt;
        if(opt == 2)
        {
            int l,r; cin >> l >> r;
            cout << query(1,1,n,l,r) << endl;
        }
        else
        {
            int l,r; ll t; cin >> l >> r >> t;
            modify(1,1,n,l,r,rfib[l-1],rfib[l]);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
	cin.tie(0);
    //fileio();

    solve();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值