銘宇巨巨推薦的題!
原題鏈結
題意:
給定乙個序列,兩種操作,一是區間求和,二是將區間裡的每個數都異或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...