HDU4533 威威猫系列故事――晒被子

题目大意

转向题目

在坐标系里面给定了N个矩形,有M次询问,每次询问输入一个t,询问的是从(0,0)到(t,t)范围内的矩形的面积(重叠也算,不是矩形面积并)


解题思路

这道题很容易让人联想到二维的做法,但是我们一看数据范围,发现是20W,明显无法满足空间限制,那么应该怎么办呢?
首先,矩形是无更新的,这给我们了非常大的空间,那么我们就可以想办法得到每一个位置的函数表达式
既然只有一个t是变元,我们可以假定t是自变量,既然是面积,一定是一个二次函数的模型
假设S=a*t^2+b*t+c,那么我们可以用三个树状数组(或线段树)维护每一个位置的啊a,b和c,我们要求的不是矩形面积并,便可以单个矩形考虑,这样就分出来三种情况
给定范围和矩形部分相交,完全含住矩形和有一条边和矩形一条边重合,由于范围是正方形,我们便需要考虑矩形的点的x坐标和y坐标的关系。
具体的就是如果x2<y2就需要考虑竖相交的诸多情况,如果x2>y2就需要考虑竖相交的诸多情况

AC代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const int maxn = (int)2e5 + 10;
struct Bitarray{
    LL T[maxn];
    int lowbit(int x){return x & (-x);}
    void clear(){memset(T, 0, sizeof(T));}
    void add(int st, int ed, LL val){
        for (int i = st; i < maxn; i += lowbit(i)) T[i] += val;
        for (int i = ed + 1; i < maxn; i += lowbit(i)) T[i] -= val;
    }
    LL query(int pos){
        LL sum = 0;
        for (int i = pos; i > 0; i -= lowbit(i)) sum += T[i];
        return sum;
    }
}A, B, C;
void fun(int st, int ed, LL a, LL b, LL c){
    A.add(st, ed, a);
    B.add(st, ed, b);
    C.add(st, ed, c);
}
int n, m;
void solve(){
    A.clear(); B.clear(); C.clear();
    scanf("%d", &n);
    LL x1, x2, y1, y2;
    for (int i = 0; i < n; i++){
        scanf("%I64d%I64d%I64d%I64d", &x1, &y1, &x2, &y2);
        if (max(x1, y1) < min(x2, y2))
            fun(max(x1, y1), min(x2, y2), 1, -(x1 + y1), x1 * y1);
        if (x2 < y2) fun(max(x2, y1) + 1, y2, 0, -x1 + x2, y1 * (x1 - x2));  
        if (y2 < x2) fun(max(y2, x1) + 1, x2, 0, -y1 + y2, x1 * (y1 - y2));
        fun(max(x2, y2) + 1, maxn, 0, 0, (x2 - x1) * (y2 - y1));
    }
    scanf("%d", &m);
    while(m--){
        LL t;
        scanf("%I64d", &t);
        LL ans = 0;
        ans += A.query(t) * t * t;
        ans += B.query(t) * t;
        ans += C.query(t);
        printf("%I64d\n", ans);
    }
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "rt", stdin);
    #endif
    int cs; cin >> cs;
    while(cs--) solve();
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值