luogu4390 [BOI2007]Mokia 摩基亚

刚入门cdq分治(入了吗),再研究研究orz

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
int n, opt, xu, yu, xv, yv, ans[10005], cnt, c[2000005];
struct Node{
    int x, y, val, idx, pos, ans;
}q[200005], tmp[200005];
bool cmp(Node u, Node v){
    if(u.x!=v.x)    return u.x<v.x;
    else if(u.y!=v.y)   return u.y<v.y;
    else    return u.pos<v.pos;
}
int lb(int x){
    return x & -x;
}
void add(int p, int x){
    if(!p)  c[0] += x;
    else
        for(; p<=n; p+=lb(p))
            c[p] += x;
}
int query(int p){
    int re=c[0];
    for(; p; p-=lb(p))
        re += c[p];
    return re;
}
void cdq(int l, int r){
    if(l==r)    return ;
    int mid=(l+r)>>1;
    for(int i=l; i<=r; i++){
        if(q[i].idx<=mid && !q[i].pos)  add(q[i].y, q[i].val);
        if(q[i].idx>mid && q[i].pos)    q[i].ans += q[i].val * query(q[i].y);
    }
    for(int i=l; i<=r; i++)
        if(q[i].idx<=mid && !q[i].pos)
            add(q[i].y, -q[i].val);
    int jj=l, kk=mid+1;
    for(int i=l; i<=r; i++)
        if(q[i].idx<=mid)   tmp[jj++] = q[i];
        else    tmp[kk++] = q[i];
    for(int i=l; i<=r; i++)
        q[i] = tmp[i];
    cdq(l, mid); cdq(mid+1, r);
}
int main(){
    cin>>n;
    cin>>n;
    while(scanf("%d", &opt)!=EOF){
        if(opt==3)  break;
        if(opt==1){
            scanf("%d %d %d", &xu, &yu, &xv);
            cnt++; q[cnt] = (Node){xu, yu, xv, cnt, 0, 0};
        }
        else{
            scanf("%d %d %d %d", &xu, &yu, &xv, &yv);
            ans[0]++;
            cnt++; q[cnt] = (Node){xu-1, yu-1, 1, cnt, ans[0], 0};
            cnt++; q[cnt] = (Node){xu-1, yv, -1, cnt, ans[0], 0};
            cnt++; q[cnt] = (Node){xv, yu-1, -1, cnt, ans[0], 0};
            cnt++; q[cnt] = (Node){xv, yv, 1, cnt, ans[0], 0};
        }
    }
    sort(q+1, q+1+cnt, cmp);
    cdq(1, cnt);
    for(int i=1; i<=cnt; i++)
        if(q[i].pos)
            ans[q[i].pos] += q[i].ans;
    for(int i=1; i<=ans[0]; i++)
        printf("%d\n", ans[i]);
    return 0;
}

转载于:https://www.cnblogs.com/poorpool/p/8988902.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值