给出
n
n
n,
o
p
t
opt
opt,
m
o
d
mod
mod,
m
i
n
min
min,
m
a
x
max
max,
m
o
d
mod
mod在 int
范围内
操作 A A A, Q Q Q
A A A: L L L, R R R, X X X 表示把 [ l , R ] [l,R] [l,R]这个区间加上 X X X
Q Q Q: L L L, R R R 表示询问 [ L , R ] [L,R] [L,R]这个区间中元素T满足 m i n < = ( T × i % m o d ) < = m a x min<=(T\times i \% mod)<=max min<=(T×i%mod)<=max 的 T这样的数的个数(i是数组下标)
你的询问操作不会超过 1000 1000 1000 次,不幸的是,对于延后的询问操作可能有很多次(小于 1 0 7 10^7 107 次),但是保证这些延后的询问操作之后不会再次有修改操作(就是在最后会有很多次询问,但不会进?修改)。
J 组算法轻松解决。
观察到 o p t opt opt 虽然有 1 0 6 10^6 106 次,但是询问操作最多只有 1000 1000 1000 次,很容易想到差分,而每次询问时直接给差分数组求前缀和统计答案即可。
而其延后操作虽然有很多次,但是没有修改,所以可以用前缀和维护前 i i i 项的合法方案数即可。
代码实现有些技巧。
#include <bits/stdc++.h>
#define int long long
/*要开long long不然会溢出*/
using namespace std;
const int N = 1e5 + 5;
int n, opt, mod, minn, maxn, final, a[N], pre[N], diff[N];
signed main(){
ios::sync_with_stdio(false);//关闭同步流
cin.tie(NULL); cout.tie(NULL);//调试用的
cin >> n >> opt >> mod >> minn >> maxn;
while(opt --){
char c;
int l, r, x;
cin >> c >> l >> r;
if(c == 'A'){
cin >> x;
diff[l] += x;//差分都会吧
diff[r + 1] -= x;
}else{
int cnt = 0;
for(int i = 1; i <= n; i ++){
a[i] = a[i - 1] + diff[i];
int tmp = (a[i] * i) % mod;//这里不要写错
if(tmp >= minn && tmp <= maxn && i >= l && i <= r){//统计合法方案数
cnt ++;
}
}
cout << cnt << "\n";
}
}
for(int i = 1; i <= n; i ++){//前缀和维护合法方案数
pre[i] = pre[i - 1];
diff[i] += diff[i - 1];//对差分数组求前缀和
int tmp = (diff[i] * i) % mod;
if(tmp >= minn && tmp <= maxn){//合法则方案数加1
pre[i] ++;
}
}
cin >> final;
while(final --){
int l, r;
cin >> l >> r;
cout << pre[r] - pre[l - 1] << "\n";//容斥原理,输出答案
}
return 0;
}