zoukankan      html  css  js  c++  java
  • CodeChef

    题目链接:https://vjudge.net/problem/CodeChef-TELEPORT

    题目大意:

      有(Q)个指令,指令为:(+) (x) (y)(在二维平面内添加一个点,坐标为((x,y)));或(?) (i) (j)(如果第(i)个指令所添加的点和第(j)个指令所添加的点联通,则打印 "DA",否则打印 “NET").

      关于联通的定义:如果每个点能到达的区域为({(a,b):|a-x|+|b-y| le R}).如果点(u)和点(v)联通,点(v)和点(k)联通,则点(u)和点(k)联通。

      (1 le Q,R,x,y le 100,000)

    知识点:  线段树、并查集

    解题思路:

      易知每个点能到达的区域为一个对角线长度为(2R)的正菱形,我们可以通过将其旋转(45^circ )来将其转换成正方形,具体的转化方法为

      (x' = x + y)

      (y' = x - y)

    而该正方形的连通区域也转变成了({(a',b'):|a'-x'|+|b'-y'| le R}).

    具体证明:(参考(chao)自官方题解

      (|x-a|+|y-b| = max(x-a+y-b, x-a+b-y, a-x+y-b, a-x+b-y) = max(|(x+y)-(a+b)|, |(x-y)-(a-b)|) = max(|x'-a'|, |y'-b'|) le R)

    (转化的部分才是本题的精髓所在)

      转化为正方形之后,对于坐标轴的 (x) 轴建立线段树,用(set)记录(x)在该区间中的中心点所对应(y)值及其指令编号。

      添加的时候先查询一下在

    ([x-2R,x] imes [y-2R,y], [x-2R,x] imes [y,y+2R], [x,x+2R] imes [y-2R, y], [x,2R] imes [y,y+2R] )

    这(4)个正方形区域中有没有点,如果有,则将各个区域中最靠近的点和要添加的点用并查集合并在一起。

      询问的时候只需询问两个点是否并在一起了即可。

      具体实现看代码及注释

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define lson l,m,rt<<1
     4 #define rson m+1,r,rt<<1|1
     5 
     6 const int maxn=500000,RR=200000;
     7 typedef pair<int,int> P; 
     8 set<P> tree[maxn<<2];   //(y值,第几次查询)
     9 void update(int pos,int y,int q,int l,int r,int rt){//在pos点插入纵坐标为y,查询编号为q的点
    10     tree[rt].insert(make_pair(y,q));
    11     if(l==r)    return;
    12     int m=(l+r)>>1;
    13     if(pos<=m)  update(pos,y,q,lson);
    14     else        update(pos,y,q,rson);
    15 }
    16 int query(int L,int R,int y,int aR,int l,int r,int rt){//查询[L,R]*[y,2*aR]的正方形区域
    17     if(L<=l&&r<=R){
    18         set<P>::iterator it=tree[rt].lower_bound(make_pair(y,0));   //找出纵坐标大于或等于y的最小值
    19         if(it != tree[rt].end() &&(it->first <= y+2*aR))   return it->second;   //返回对应的编号(从1开始)
    20         return 0;//否则返回0
    21     }
    22     int m=(l+r)>>1;
    23     int ret=0;
    24     if(L<=m)  ret=max(ret,query(L,min(m,R),y,aR,lson));
    25     if(R>m)   ret=max(ret,query(max(L,m+1),R,y,aR,rson));
    26     return ret;
    27 }
    28 
    29 //并查集部分
    30 int par[maxn];
    31 void init(int n){
    32     for(int i=0;i<=n;i++)   par[i]=i;
    33 }
    34 int finds(int x){
    35     if(par[x]==x)   return x;
    36     return par[x]=finds(par[x]);
    37 }
    38 void unite(int x,int y){
    39     int tx=finds(x);
    40     int ty=finds(y);
    41     if(tx==ty)  return;
    42     par[tx]=ty;
    43 }
    44 //*******************************************************
    45 int main(){
    46     int Q,R,x,y;
    47     char tmp[5];
    48     scanf("%d%d",&Q,&R);
    49     init(Q);
    50     for(int q=1;q<=Q;q++){
    51         scanf("%s %d %d",tmp,&x,&y);
    52         int tx=x+y+2*R,ty=x-y;  //因为后面会查询到[tx-2*R,tx]这个区间,所以我们统一先将其加上2*R,避免出现负数,数组也要相应地开大一点
    53         if(tmp[0]=='+'){
    54             int x1=query(tx-2*R,tx,ty-2*R,R,1,maxn,1);
    55             int x2=query(tx-2*R,tx,ty,R,1,maxn,1);
    56             int x3=query(tx,tx+2*R,ty-2*R,R,1,maxn,1);
    57             int x4=query(tx,tx+2*R,ty,R,1,maxn,1);
    58             if(x1)  unite(x1,q);
    59             if(x2)  unite(x2,q);
    60             if(x3)  unite(x3,q);
    61             if(x4)  unite(x4,q);
    62             update(tx,ty,q,1,maxn,1);
    63         }
    64         else{
    65             if(finds(x)==finds(y))  printf("DA
    ");
    66             else    printf("NET
    ");
    67         }
    68     }
    69 }

         

    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    Poj 1742 Coins(多重背包)
    Poj 2350 Above Average(精度控制)
    求二进制数中1的个数
    Poj 1659 Distance on Chessboard(国际象棋的走子规则)
    Poj 2411 Mondriaan's Dream(压缩矩阵DP)
    Poj 2136 Vertical Histogram(打印垂直直方图)
    Poj 1401 Factorial(计算N!尾数0的个数——质因数分解)
    poj 2390 Bank Interest(计算本利和)
    Poj 2533 Longest Ordered Subsequence(LIS)
    Poj 1887 Testing the CATCHER(LIS)
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/8344089.html
Copyright © 2011-2022 走看看