2019ICPC南京网络赛A(离线树状数组)

题目链接

分析:一次询问可以分为四次前缀询问,将每次询问按照y升序排序,维护一个x上的树状数组就行了。难点在于计算对应点的值(不会~?~)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
ll bit[maxn], ans[maxn];
struct node
{
    int f, x, y, id, k;
    friend bool operator<(node a, node b)
    {
        if (a.y == b.y)
        {
            if (a.x == b.x)
                return abs(a.f) < abs(b.f);
            else
                return a.x < b.x;
        }
        else
            return a.y < b.y;
    }
} a[maxn];
int realv(ll n)
{
    int tmp = 0;
    while (n)
        tmp += n % 10, n /= 10;
    return tmp;
}
ll index(ll y, ll x, ll n)
{
    ll mid = (n + 1) / 2;
    ll p = max(abs(x - mid), abs(y - mid));
    ll ans = n * n - (1 + p) * p * 4;
    ll sx = mid + p, sy = mid + p;
    if (x == sx && y == sy)
        return ans;
    else
    {
        if (y == sy || x == sx - 2 * p)
            return ans + abs(x - sx) + abs(y - sy);
        else
            return ans + 8 * p - abs(x - sx) - abs(y - sy);
    }
}
ll sum(int x)
{
    ll an = 0;
    while (x)
    {
        an += bit[x];
        x -= x & -x;
    }
    return an;
}
void update(int id, int n, ll k)
{
    while (id <= n)
    {
        bit[id] += k;
        id += id & -id;
    }
}
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int n, m, q;
        scanf("%d%d%d", &n, &m, &q);
        memset(bit, 0, sizeof(bit));
        memset(ans, 0, sizeof(ans));
        int x, y;
        int cnt = 0;
        for (int i = 1; i <= m; ++i)
        {
            scanf("%d%d", &x, &y);
            a[++cnt] = {0, x, y, 0, realv(index(x, y, n))};
        }
        int x1, y1, x2, y2;
        for (int i = 1; i <= q; ++i)
        {
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            a[++cnt] = {1, x1 - 1, y1 - 1, i, 0};
            a[++cnt] = {-1, x1 - 1, y2, i, 0};
            a[++cnt] = {-1, x2, y1 - 1, i, 0};
            a[++cnt] = {1, x2, y2, i, 0};
        }
        sort(a + 1, a + 1 + cnt);
        for (int i = 1; i <= cnt; ++i)
        {
            if (a[i].f)
                ans[a[i].id] += sum(a[i].x) * a[i].f;
            else
                update(a[i].x, n, a[i].k);
        }
        for (int i = 1; i <= q; ++i)
            printf("%lld\n", ans[i]);
    }
    return 0;
}

  

 

posted @ 2019-09-02 22:33  tryatry  阅读(86)  评论(0编辑  收藏  举报