解法:我们对每个数字建立动态开点01线段树,线段树维护区间内区间和为奇数的子区间个数,然后就是一个水题了…我们对每个区间维护这5个信息:val,len,sumL,sumR,sum,分别表示区间和为奇数的的子区间个数,区间长度,包含左端点且区间和为奇数的区间个数,包含右端点且区间和为奇数的个数,区间和,然后我们就只有一个问题:区间合并,我们用ls,rs表示左儿子,右儿子,很显然
v
a
l
+
=
v
a
l
[
l
s
]
+
v
a
l
[
r
s
]
val+=val[ls]+val[rs]
val+=val[ls]+val[rs],那么我们还需要计算左儿子区间右端点和右儿子区间左端点拼接的合法区间,左儿子区间和奇数+右儿子区间和偶数:
v
a
l
+
=
s
u
m
R
[
l
s
]
∗
(
l
e
n
[
r
s
]
−
s
u
m
L
[
r
s
]
)
val+=sumR[ls]*(len[rs]-sumL[rs])
val+=sumR[ls]∗(len[rs]−sumL[rs]),左儿子区间和偶数+右儿子区间和奇数:
v
a
l
+
=
(
l
e
n
[
l
s
]
−
s
u
m
R
[
l
s
]
)
∗
s
u
m
L
[
r
s
]
val+=(len[ls] - sumR[ls])*sumL[rs]
val+=(len[ls]−sumR[ls])∗sumL[rs],sumL,sumR的合并亦同理,不多说了
#include<bits/stdc++.h>#define ll long long
using namespace std;constint maxn =4e5+10;
map<int,int> mp;int rt[maxn], ls[maxn *20], rs[maxn *20], a[maxn], cnt, cnt2;struct node {
ll val;int len, sumL, sumR, sum;
node operator+(const node &t)const{
node tmp;
tmp.val = val + t.val;
tmp.val +=1ll* sumR *(t.len - t.sumL);
tmp.val +=1ll*(len - sumR)* t.sumL;
tmp.len = len + t.len;
tmp.sum = sum + t.sum;if(sum %2)
tmp.sumL = sumL + t.len - t.sumL;else
tmp.sumL = sumL + t.sumL;if(t.sum %2)
tmp.sumR = t.sumR + len - sumR;else
tmp.sumR = t.sumR + sumR;return tmp;}} tree[maxn *20];voidinit(int&o,int len){
o =++cnt;
tree[o].len = len;}voidup(int&o,int l,int r,int k,int v){if(!o)
o =++cnt;if(l == r){
tree[o].val = tree[o].sumL = tree[o].sumR = tree[o].sum = v;
tree[o].len =1;return;}int m =(l + r)/2;if(k <= m)up(ls[o], l ,m, k, v);elseup(rs[o], m +1, r, k, v);if(!ls[o])//细节,如果空节点也需要填上区间长度,以防出错init(ls[o], m - l +1);if(!rs[o])init(rs[o], r - m);
tree[o]= tree[ls[o]]+ tree[rs[o]];}
node qu(int& o,int l,int r,int ql,int qr){if(!o)init(o, r - l +1);//同上的细节if(l >= ql && r <= qr)return tree[o];int m =(l + r)/2;if(qr <= m)returnqu(ls[o], l, m, ql, qr);elseif(ql > m)returnqu(rs[o], m +1, r, ql, qr);returnqu(ls[o], l, m, ql, qr)+qu(rs[o], m +1, r, ql, qr);}intmain(){int n, x, q, opt, v, l, r;scanf("%d",&n);for(int i =1; i <= n; i++){scanf("%d",&a[i]);if(!mp.count(a[i]))
mp[a[i]]=++cnt2;up(rt[mp[a[i]]],1, n, i,1);}scanf("%d",&q);while(q--){scanf("%d",&opt);if(opt ==1){scanf("%d%d",&x,&v);up(rt[mp[a[x]]],1, n, x,0);
a[x]= v;if(!mp[a[x]])
mp[a[x]]=++cnt2;up(rt[mp[a[x]]],1, n, x,1);}else{scanf("%d%d%d",&l,&r,&x);printf("%lld\n",qu(rt[mp[x]],1, n, l, r).val);}}}