1752. [BOI2007]摩基亚Mokia (cdq分治模板题)

题目:1752. [BOI2007]摩基亚Mokia

cdq分治论文中的题目,通过cdq分治可以做到降维,然后用树状数组维护就可以了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

#define CLR(a, b) memset(a, b, sizeof(a))
#define LL long long

using namespace std;

const int maxn = 2002000;

LL c[maxn], ans[maxn];

struct query
{
    int x, y, type, v, id, q;
    query() {}
    query(int x, int y, int v, int type, int id, int q)
        :x(x), y(y), v(v), type(type), id(id), q(q) {}
    bool operator < (const query& rhs) const
    {
        return x < rhs.x;
    }
}Q[maxn];

int W;

int lowbit(int x)
{
    return x & (-x);
}

void add(int x, LL ad)
{
    while(x <= W)
    {
        c[x] += ad;
        x += lowbit(x);
    }
}

LL sum(int x)
{
    LL ret = 0;
    while(x)
    {
        ret += c[x];
        x -= lowbit(x);
    }
    return ret;
}

void cdq(int l, int r)
{
    if(l == r) return ;
    int m = (l + r) >> 1;
    cdq(l, m); cdq(m + 1, r);
    sort(Q + l, Q + m + 1);
    sort(Q + m + 1, Q + r + 1);
    int now = l;
    for(int i = m + 1; i <= r; i ++)
    {
        while(now <= m && Q[now].x <= Q[i].x)
        {
            if(Q[now].type == 1) add(Q[now].y, Q[now].v);
            now ++;
        }
        if(Q[i].type == 2) ans[Q[i].q] += Q[i].v * sum(Q[i].y);
    }
    for(int i = l; i < now; i ++)
    {
        if(Q[i].type == 1) add(Q[i].y, -Q[i].v);
    }
}

int main()
{
//    freopen("mokia.in", "r", stdin);
//    freopen("mokia.out", "w", stdout);
    int op;
    scanf("%d%d", &op, &W);
    int tot = 0, qsiz = 1;
    while(scanf("%d", &op))
    {
        if(op == 3) break;
        if(op == 1)
        {
            int x, y, v;
            scanf("%d%d%d", &x, &y, &v);
            tot ++;
            Q[tot] = query(x, y, v, 1, tot, 0);
        }
        else
        {
            int x1, x2, y1, y2;
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            tot ++;
            Q[tot] = query(x1 - 1, y1 - 1, 1, 2, tot, qsiz);
            tot ++;
            Q[tot] = query(x1 - 1, y2, -1, 2, tot, qsiz);
            tot ++;
            Q[tot] = query(x2, y1 - 1, -1, 2, tot, qsiz);
            tot ++;
            Q[tot] = query(x2, y2, 1, 2, tot, qsiz);
            qsiz ++;
        }
    }
    CLR(c, 0); CLR(ans, 0);
    cdq(1, tot);
    for(int i = 1; i < qsiz; i ++)
        printf("%I64d\n", ans[i]);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值