题目连接
题意:
开始每个数组的元素都是0
给出n . opt, mod, min, max, mod在int内
操作 A, Q
A:L, R, X 吧 [ L, R ] 这个区间内每个元素+ X
Q:L, R 询问 [L, R] 这个区间中元素满足
min <= (T * i % mod) <= max 的T这样的数的个数
(i是数组下标)
在给出一个Final值,表示有Final 个查询
[ L, R ] 表示 询问区间 [L, R] 之间满足条件的个数
思路:
数据范围:N 8e4, opt 1e6, Final 1e7, Q <= 1e3
时间1S
那么A的操作就是 1e6 -1e3 = 差不多还是1e6
操作过后直接 前缀数组 O(N) 求一下然后就是 Final操作了
1)如果用线段树 时间就是 O(Log(2)8e4 * 1e6 + log(2)8e4 * 1e7)
2)用差分数组 O(1e3 * N + 1e6 + N + Final)
AC:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<stdio.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5;
ll N, opt, Mod, Min, Max, Final;
ll F[maxn];
ll Pre[maxn];
ll Solve(int L, int R) {
ll T = 0;
for(int i = 1; i < L; ++i) {
T += F[i];
}
ll Ans = 0;
ll Tmp;
for (int i = L; i <= R; ++i) {
T += F[i];
Tmp = T * i % Mod;
if ( Tmp >= Min && Max >= Tmp) {
Ans ++;
}
}
return Ans;
}
void bulid() {
ll Tmp = 0;
ll T = 0;
int Flag = 0;
for(int i = 1; i <= N; ++i) {
T += F[i];
Tmp = T * i % Mod;
Flag = 0;
if( Tmp >= Min && Max >= Tmp) {
Flag = 1;
}
Pre[i] = Pre[i - 1] + Flag;
}
}
int main() {
//freopen("in.txt", "r", stdin);
scanf("%lld%lld%lld%lld%lld", &N, &opt, &Mod, &Min, &Max);
char ch[3];
ll L, R, X;
ll Ans = 0;
for(int i = 1; i <= opt ; ++i) {
scanf("%s", &ch);
if(ch[0] == 'A') {
scanf("%lld%lld%lld", &L, &R, &X);
F[L] += X;
F[R + 1] -= X;
}
if(ch[0] == 'Q') {
scanf("%lld%lld", &L, &R);
Ans = Solve(L, R);
printf("%lld\n", Ans);
}
}
scanf("%lld", &Final);
bulid();
for(int i = 1; i <= Final; ++i) {
scanf("%lld%lld", &L, &R);
printf("%lld\n", Pre[R] - Pre[L - 1]);
}
return 0;
}