題目鏈接:點我啊╭(╯^╰)╮
解題思路:
如果只考慮,也就是一段連續的區間,預處理前綴即可
而,加上了一個異或後,區間就不連續了
根據異或性質,會分成最多 個連續區間
從高位到低位考慮,如果 的第 位爲 ,若不考慮 的低位
若 的這一位爲 ,則異或後是一段連續的區間:
若 的這一位爲 ,區間加上這一位即可
每一位考慮完之後,要加上這一位的影響,再去考慮低位
最後要清空影響,其實最後的影響就是 了
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <int,int>;
const ll mod = 998244353;
const int maxn = 1e5 + 5;
int n, q, a[maxn];
ll pre[maxn];
vector <int> v;
ll gao(ll x){
if(x < a[1]) return 0;
int pos = upper_bound(v.begin(), v.end(), x) - v.begin() - 1;
ll ret = pre[pos];
if(x == v[pos]) return ret;
ll num = upper_bound(a+1, a+1+n, x) - a - 1;
ret += 1ll * (x - v[pos]) * num % mod * num % mod;
return ret % mod;
}
ll query(int l, int r){
return (gao(r) - gao(l-1) + mod) % mod;
}
ll solve(int n, int x){
if(n < 0) return 0;
ll ret = 0; int cur = 0;
for(int i=30; ~i; i--){
int u = x >> i & 1;
if(n >> i & 1){
ret += query(cur|(u<<i), (cur|(u<<i)) + (1<<i)-1);
cur |= ((u ^ 1) << i);
} else cur |= (u << i);
}
ret = (ret + query(cur, cur)) % mod;
return ret;
}
int main() {
scanf("%d%d", &n, &q);
for(int i=1; i<=n; i++) scanf("%d", a+i), v.push_back(a[i]);
sort(a+1, a+1+n);
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
ll cnt = v.size(), num, lnum;
for(int i=0; i<cnt; i++){
num = upper_bound(a+1, a+1+n, v[i]) - a - 1;
if(i == 0) pre[i] = num * num % mod;
else pre[i] = pre[i-1] + num * num % mod + \
(v[i] - v[i-1] - 1) * lnum % mod * lnum % mod;
pre[i] %= mod;
lnum = num;
}
while(q--){
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
ll ans = solve(r, x) - solve(l-1, x);
printf("%lld\n", (ans + mod) % mod);
}
}