Codeforces Round #468 (Div. 1) D: Game with Tokens(扫描线)

传送门

题解:
注意到白点不被挡住的情况一定是白点一直往一个方向走。

不妨考虑一个黑点能挡住某个方向的哪些白点,画图可以发现是四周的三角形区域。

对于三角形区域,可以通过坐标旋转来转化为矩阵区域,之后问题便转化为:给四种颜色的一些区域,问有哪些区域同时有四种颜色,直接扫描线即可。

(细节有点多直接抄的楼教主的代码。。)

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
inline int rd() {
    char ch=getchar(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
    return i*f;
}
const int N=1e5+50;
int n,xc[N],yc[N];
multiset <int> s1,s2;
vector <pii> s;
inline LL solve(int odd) {
    LL rs=0;
    s.clear(); s1.clear(); s2.clear();
    for(int i=1;i<=n;i++) if((xc[i]&1)==odd) s.push_back(make_pair((xc[i]+odd)/2,(yc[i]+odd)/2));
    if(!s.size()) return 0;
    sort(s.begin(), s.end());
    for(int i=0;i<s.size();i++)
        s2.insert(s[i].second);
    for(int x0=s.front().first,p1=0,p2=0;x0<=s.back().first;++x0) {
        while(p1<s.size() && s[p1].first<=x0) s1.insert(s[p1++].second);
        while(p2<s.size() && s[p2].first<=x0) s2.erase(s2.find(s[p2++].second));
        if(s1.size() && s2.size()) {
            int t=max(*s1.begin(),*s2.begin()), u=min(*s1.rbegin(),*s2.rbegin());
            if(u>t) rs+=u-t;
        }
    }
    return rs;
}
int main() {
    n=rd();
    for(int i=1;i<=n;i++) {
        int x=rd(), y=rd();
        xc[i]=(x-y);
        yc[i]=(x+y);
    }
    cout<<solve(0)+solve(1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值