暴力出奇迹!
讲道理,刚看到什么数组乘以下标,我就已经吓傻了。
woc,区间加还不能用差分,这怎么可能做得了啊
其实暴力就完事了。
先看看数据范围:\(n \leq 80000, opt \leq 1000000, Q \leq 1000, Final \leq 10000000\)
这能够说明什么?
说明修改操作特别多,而查询操作特别少。最后最多的查询是在Final部分的。
既然查询操作少,我们就让它暴力去跑就可以了呀!
修改是区间加,可以直接用差分数组\(O(1)\)修改,而查询最多也就\(1000 \times 80000=8\times 10^7\)。
然后就是Final部分。显然我们要做到\(O(1)\)的应对查询。
因为每个值都已经固定不变,所以我们可以直接算出每一个点是否可行。然后用前缀和弄一下,区间查询就减一下就可以了。
其实这道题最良心的点在于:
暴力都能拿74分!并且比写挂的算法还多分!
代码:
#include<cstdio>
#define ll long long
const int maxn = 80005;
ll a[maxn], b[maxn];
ll n, m, mod, minv, maxv, Final;
ll read()
{
ll ans = 0, s = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar();
return s * ans;
}
int main()
{
n = read(), m = read(), mod = read(), minv = read(), maxv = read();
char opt[3];
while(m--)
{
scanf("%s", opt);
if(opt[0] == 'A')
{
int l = read(), r = read(); ll x = read();
a[l] += x; a[r + 1] -= x;
}
else if(opt[0] == 'Q')
{
int l = read(), r = read();
int cnt = 0; ll now = 0;
for(int i = 1; i <= r; i++)
{
now += a[i];
if(i >= l && now * i % mod >= minv && now * i % mod <= maxv) cnt++;
}
printf("%d\n", cnt);
}
}
ll now = 0;
for(int i = 1; i <= n; i++)
{
now += a[i];
if(now * i % mod >= minv && now * i % mod <= maxv) b[i] = 1;
else b[i] = 0;
b[i] += b[i - 1];
}
Final = read();
while(Final--)
{
int l = read(), r = read();
printf("%d\n", b[r] - b[l - 1]);
}
return 0;
}