牛客 紅球進黑洞 (線段樹 位運算)

2021-10-08 21:34:24 字數 2485 閱讀 5304

銘宇巨巨推薦的題!

原題鏈結

題意:

給定乙個序列,兩種操作,一是區間求和,二是將區間裡的每個數都異或x。

思路:

一眼就線段樹,關鍵是怎麼維護第二個操作。

借助最小異或生成樹的思想以及異或題的常見套路,我們可以把每個數都進行二進位制拆分,用線段樹分別維護每一位上的0和1。

對於操作二,我們只需要分別維護每一位的值即可;對於操作一,計算區間裡1的個數乘以對應的位數,就相當於是二進位制轉化為十進位制的過程。

**:

#pragma gcc optimize(3)

#pragma gcc optimize("ofast","unroll-loops","omit-frame-pointer","inline")

#include

using

namespace std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

typedef pairpll;

typedef pair<

int,

int>pii;

typedef pair<

double

,double

>pdd;

#define i_int ll

#define x first

#define y second

inline ll read()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}char f[

200]

;inline

void

out(i_int x)

while

(cnt >0)

putchar

(f[--cnt]);

//cout<<" ";

}ll ksm

(ll a,ll b,ll p)

return res;

}const

int inf=

0x3f3f3f3f

,mod=

1e9+7;

const ll inf =

0x3f3f3f3f3f3f3f3f

;const

int maxn=

1e5+

10,maxm=

3e6+7;

const

double pi =

atan

(1.0)*

4;struct nodetr[25]

[maxn*4]

;int a[maxn]

;int n,m,k;

void

pushup

(int cnt,

int u)

void

pushdown

(int cnt,

int u)

///異或後1的個數 = 原來0的個數 = 區間長度(總個數)- 異或前1的個數

}void

build

(int cnt,

int u,

int l,

int r);if

(l==r)

int mid=

(l+r)

>>1;

build

(cnt,u<<

1,l,mid)

;build

(cnt,u<<1|

1,mid+

1,r)

;pushup

(cnt,u);}

///update(i,1,ql,qr,k&1);

void

update

(int cnt,

int u,

int ql,

int qr,

int x)

pushdown

(cnt,u)

;int mid=

(tr[cnt]

[u].l+tr[cnt]

[u].r)

>>1;

if(ql<=mid)

update

(cnt,u<<

1,ql,qr,x);if

(qr>mid)

update

(cnt,u<<1|

1,ql,qr,x)

;pushup

(cnt,u);}

///qask(i,1,ql,qr);

ll qask

(int cnt,

int u,

int ql,

int qr)

intmain()

else}}

return0;

}

參考部落格

牛客小白月賽9 C 紅球進黑洞

思路 線段樹,對於區間異或,可以對數的每一位都建立一顆線段樹,區間異或時,對於當前位為0的不用考慮,當前位為1時,則將區間的0 1,1 0,即更新為 sum i r l 1 sum i 即可 code include include include define lc rt 1 define lso...

sequence 牛客 ( 線段樹)

題面 your are given two sequences a1 n,b1 n a b a1 n b1 n you need to answer max 1 l r n displaystyle max times sum b 1 l r nmax 1e 6 b i 1e 6 1e6 1 e6 ...

帶 sin, cos 的線段樹 牛客

題意 給你 n 個數字,第一種操作是將乙個區間內每乙個數字加上同乙個數字,第二種操作是求乙個區間內每乙個數 sin 的累加和 思路分析 對於每個區間維護一下 cos 和 sin 的值,當乙個區間要加上乙個數字時,此時再重新計算 sin的值時 sin a x sin a cos x cos a sin...