BZOJ1182 Croatian2009 PLAHTE

提示:
1. 可以尝试算算每个矩形覆盖面积的二次差分

详细题解在代码后:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>

using namespace std;
const int maxt = 1e6+1e2;
typedef long long ll;

int re() {
    int n = 0, ch = getchar(); bool flag = false;
    while(!isdigit(ch)) flag |= ch == '-', ch = getchar();
    while(isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
    return flag ? -n : n;
}

int x1 , y1 , x2 , y2;

ll square(int t)
{
    ll x = min(t , x2) - max(-t , x1)+1;
    ll y = min(t , y2) - max(-t , y1)+1;
    return (x<=0 || y<=0) ? 0 : x*y;
}

int a[maxt] , a2[maxt] , a4[maxt] , b[maxt];

void modify(int t1 , int t2)
{
    ll p0 = square(t1-1);
    ll p1 = square(t1  );
    ll p2 = square(t1+1);

    a[t1] += p1-p0;
    a[t2] -= p1-p0;

    if(t2>t1+1)
    {
        ll v = p2-2*p1+p0;
        a[t2] -= v*(t2-t1);
        if(v == 2) a2[t1]++ , --a2[t2];
        if(v == 4) a4[t1]++ , --a4[t2];
    }
}


int main(int argc, char *argv[]) {

    int n;
    int q[20];
    cin>>n;

    for(int i=1;i<=n;i++)
    {
        x1 = re(); y1 = re(); x2 = re(); y2 = re();

        for(int d=-1 , cnt=0;d<=1;d++)
        {
            q[cnt++] = abs(x1+d);
            q[cnt++] = abs(x2+d);
            q[cnt++] = abs(y1+d);
            q[cnt++] = abs(y2+d);
        }

        sort(q, q+12);
        for(int i=1;i<12;i++) modify(q[i-1], q[i]);
    }

    cin>>n;
    int Mx = 0;
    for(int i=1;i<=n;i++) 
    {
        x1 = re();
        b[x1] = 1;
        Mx = max(Mx , x1);
    }

    ll res = 0 , add=0 , k2=0 , k4=0;
    for(int i=0;i<=Mx;i++)
    {
        res+= add+=a[i];
        add+= 2*(k2+=a2[i])+4*(k4+=a4[i]);
        if(b[i]) printf("%lld\n" , res);
    }


    return 0;
}

首先每个矩形的关键时刻最多12个 , 我并不确定哪些是真正的变化时刻 , 但不要紧 , 都记录一下不会错。

于是我把矩形分成若干时刻 , 在这些时刻之间矩形的面积增长是一定的。 于是查分记录一下就好。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值