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

传送门

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

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

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

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

#include 
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  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;ifor(int x0=s.front().first,p1=0,p2=0;x0<=s.back().first;++x0) {
        while(p1while(p2if(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<0)+solve(1);
}

你可能感兴趣的:(扫描线)