P3948 数据结构

暴力出奇迹!

讲道理,刚看到什么数组乘以下标,我就已经吓傻了。

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;
}
posted @ 2018-10-28 22:04  Garen-Wang  阅读(184)  评论(0编辑  收藏  举报