码迷,mamicode.com
首页 > 其他好文 > 详细

[Codeforces]856E Satellites

时间:2017-09-15 18:44:25      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:priority   else   .com   cdq分治   nlog   friend   条件   能力   开始   

  二维询问转化成一维询问的问题,话说CF上面的好题还真多。

 

Description

  给定一个半径为r的半圆,圆心为坐标原点O,直径为AB,半圆弧位于x轴上方。给定n次操作,每次为以下3种操作之一:

    ①1 x y — 在(x,y)处放置一颗卫星,如果该卫星是第 i 个被放到平面上的卫星,则它的编号为i;

    ②2 i — 移除编号为 i 的卫星;

    ③3 i j — 对卫星 i 和卫星 j 进行询问,若在卫星 i 和卫星 j 的公共控制区域能够找到一个点,满足这个点不被其他卫星所控制,那么输出"YES",否则输出"NO"。

  一颗卫星点P的控制区域为△PAB中的不在⊙O内的部分。如下图绿色区域:

    技术分享

Input

  第一行两个整数r,n。

  接下来n行,每行表示一个操作。

Output

  对于每个操作3,输出"YES"或“NO”。

Sample Input

  5 8
  1 -5 8
  1 -4 8
  1 -3 8
  1 2 7
  3 1 3
  2 2
  3 1 3
  3 3 4

Sample Output

  NO
  YES
  YES

HINT

  1<=r<=10^9,1<=n<=5*10^5。

  |x|<=10^9,0<y<=10^9,且(x,y)保证在圆外。

  对于操作2、3中的i、j,满足在执行此操作之前,卫星 i 和卫星 j 一定在平面上。

 

Solution

  又是这样一道带操作的题,在开始打数据结构之前,我们分析一下题意:

  操作1和操作2分别是插入和删除操作,而操作3是在询问两个二维平面的交 内是否有不被其他区间覆盖的点。

  很显然就是叫我们求如下图的绿色区域内是否有其他卫星。

    技术分享

  那么绿色区域内的卫星P满足什么条件呢?用k(α)表示直线α与x轴正方向的夹角,那么有:

    k(AP)>k(AP2)且k(BP)<k(BP1)。

  这么一来,做法一下子就变得显而易见了。

  对于每个点Pi,把k(BPi)看作第一维,把k(APi)看作第二维,维护第二维出现的次数,目的是求和,判定条件是 和是否大于0。

  然而数据范围是50W,如果你头戴金刚钻是可以用cdq分治O(nlog2n)通过该题的。

  我们继续分析这道题的性质:我们发现两维的询问都是在询问整段序列的一半,而且判定条件是和大于1即可。

  所以我们只要对于每个第一维,维护第二维的最大值,这样就变成了求矩形最大值,判定条件是 求得的最大值是否超过限制(你懂的)。

  而且这个矩形最大值实际上只跟第一维有关系,询问的是第二维的全部,所以我们用线段树套堆就可以将复杂度降为O(nlogn)。

  具体做法什么的只要脑补一下就行了。

  最需要注意的是这题可能会带来精度上的困扰,所以各种计算和判定尽量使用向量来进行。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define ll long long
#define l(a) (a<<1)
#define r(a) (a<<1|1)
#define MN 500005
#define MD 1100005
using namespace std;
struct vec
{
    int x,y;
    friend ll operator/(const vec& a,const vec& b) {return 1LL*a.x*b.y-1LL*a.y*b.x;}
    friend ll operator*(const vec& a,const vec& b) {return 1LL*a.x*b.x+1LL*a.y*b.y;}
};
struct meg{int g,x,y;}a[MN];
struct met{vec v;int pos;}b0[MN],b1[MN];
struct its{int x,y;}s[MN];
struct itv{vec x,y;}d[MN];
struct Que
{
    priority_queue <int> A,B;
    void push(int x) {A.push(x);}
    void dele(int x) {B.push(x);}
    int top()
    {
        while (!B.empty()&&A.top()==B.top()) A.pop(),B.pop();
        if (!A.empty()) return A.top(); else return 0;
    }
}q[MN];
int m,MQ,tin,b0in,b1in,ra;
int t[MD];

inline int read()
{
    int n=0,f=1; char c=getchar();
    while (c<0 || c>9) {if(c==-)f=-1; c=getchar();}
    while (c>=0 && c<=9) {n=n*10+c-0; c=getchar();}
    return n*f;
}

inline void getcg(int x,int z) {for (t[x+=MQ]=z,x>>=1;x;x>>=1) t[x]=max(t[l(x)],t[r(x)]);}
inline int getmax(int L,int R)
{
    int sum=0;
    for (L+=MQ,R+=MQ;L<=R;L>>=1,R>>=1)
    {
        if ( L&1) sum=max(sum,t[L++]);
        if (~R&1) sum=max(sum,t[R--]);
    }
    return sum;
}

void cghp(int x,int y,int g)
{
    int lt=q[x].top();
    if (g==1) q[x].push(y); else q[x].dele(y);
    if (lt!=q[x].top()) getcg(x,q[x].top());
}

bool check(int x,int y)
{
    int cs1,cs2;
    if (s[x].x>s[y].x) cs1=x; else cs1=y;
    if (s[x].y<s[y].y) cs2=x; else cs2=y;
    if (d[cs2].y*d[cs1].x<0) return true; else return false;
}

bool cmp(const met& a,const met& b) {return a.v/b.v>0;}

int main()
{
    register int i,x,y;
    ra=read(); m=read();
    for (i=1;i<=m;++i)
    {
        a[i].g=read();
        if (a[i].g==1)
        {
            x=read(); y=read(); a[i].x=++tin;
            d[tin].x.x=x-ra; d[tin].x.y=y;
            d[tin].y.x=x+ra; d[tin].y.y=y;
            b0[++b0in]=(met){d[tin].x,tin};
            b1[++b1in]=(met){d[tin].y,tin};
        }
        else if (a[i].g==2) a[i].x=read();
        else if (a[i].g==3) a[i].x=read(),a[i].y=read();
    }
    sort(b0+1,b0+b0in+1,cmp); sort(b1+1,b1+b1in+1,cmp);
    b0[0].pos=b1[0].pos=s[0].x=s[0].y=0;
    for (i=1;i<=b0in;++i)
        if (i>1&&b0[i-1].v/b0[i].v==0) s[b0[i].pos].x=s[b0[i-1].pos].x;
        else s[b0[i].pos].x=s[b0[i-1].pos].x+1;
    for (i=1;i<=b1in;++i)
        if (i>1&&b1[i-1].v/b1[i].v==0) s[b1[i].pos].y=s[b1[i-1].pos].y;
        else s[b1[i].pos].y=s[b1[i-1].pos].y+1;
    b0in=s[b0[b0in].pos].x;
    for (MQ=1;MQ<b0in;MQ<<=1); --MQ;
    for (i=1;i<=m;++i)
    {
        if (a[i].g<3) cghp(s[a[i].x].x,s[a[i].x].y,a[i].g);
        else if (a[i].g==3)
        {
            if (check(a[i].x,a[i].y)) {puts("NO"); continue;}
            x=max(s[a[i].x].x,s[a[i].y].x); y=min(s[a[i].x].y,s[a[i].y].y);
            cghp(s[a[i].x].x,s[a[i].x].y,2);
            cghp(s[a[i].y].x,s[a[i].y].y,2);
            if (getmax(1,x)>=y) puts("NO"); else puts("YES");
            cghp(s[a[i].x].x,s[a[i].x].y,1);
            cghp(s[a[i].y].x,s[a[i].y].y,1);
        }
    }
}

 

Last Word

  又一次感受到了精度在某些题使人发狂程度的能力。

  然后就不得不感叹一句向量真是好用。

[Codeforces]856E Satellites

标签:priority   else   .com   cdq分治   nlog   friend   条件   能力   开始   

原文地址:http://www.cnblogs.com/ACMLCZH/p/7526216.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!