zoukankan      html  css  js  c++  java
  • 刷题总结——天使玩偶(bzoj2716)

    题目:

    Description

    Input

    Output

    HINT

    题解:

      学了cdq后近期最后一道题···然而tm还是搞了1个半小时才tm搞出来······

      先说思路:对于绝对值,我们采取类似于旋转整个图的方法,也就是说共计三次翻转再加上原来的图,每次旋转90度,算出点在旋转后的对应坐标(具体看代码中的注释部分),然后对于一个询问,每次只算它左上角的点的贡献,这样就有一个三维偏序:<时间,x,y>,时间已经在开始就默认排好了,由于此时dis=x-x1+y-y1=x+y-x1-y1,所以对于一个<时间,x,y>,我们要计算的是所有x1<x,y1<y,时间1<时间的点中x1+y1最大的点,这样dis就能最小;分析完基本思路后,接下来就是cdq的基本套路了,x1+y1用树状数组维护

      但这道题让我发现了自己的许多细节错误,详细见代码注释

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=2e6+5;
    const int M=5e5+5;
    struct node
    {
      int x,y,id,pos;
    }a[N],q[N],tmp[N];
    int n,m,tot,maxx,maxy,ans[M],cnt=0,tree[N],tag[N],tim;
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())
        f=(f<<3)+(f<<1)+c-'0';
      return f;
    }
    bool comp(node a,node b)
    {
      if(a.x==b.x)  return a.id<b.id;  //!!!!!注意一定要有这一点,x相同时一定要按时间排序!! 
      else return a.x<b.x;
    }
    inline void insert(int u,int v)
    { 
      for(int i=u;i<=maxy;i+=(i&(-i)))
        if(tag[i]!=tim)  tag[i]=tim,tree[i]=v;
        else tree[i]=max(tree[i],v);
    }
    inline int query(int u)
    {
      int temp=0;
      for(int i=u;i;i-=(i&(-i)))
        if(tag[i]!=tim)  continue;
        else temp=max(temp,tree[i]);
      return temp==0?-1e+8:temp;   //注意这里!!! 
    }
    inline void solve(int l,int r)
    {
      if(l==r)  return; 
      int mid=(l+r)/2;
      solve(l,mid),solve(mid+1,r);
      int i=l,j=mid+1,k=l;tim++;
      while(i<=mid&&j<=r)
      {
        if(comp(q[i],q[j]))
        {
          if(!q[i].pos)  insert(q[i].y,q[i].x+q[i].y);
          tmp[k++]=q[i++];
        }
        else
        {
          if(q[j].pos)  ans[q[j].pos]=min(ans[q[j].pos],q[j].x+q[j].y-query(q[j].y));
          tmp[k++]=q[j++];
        }
      }
      while(i<=mid)  tmp[k++]=q[i++];
      while(j<=r)
      {
        if(q[j].pos)  ans[q[j].pos]=min(ans[q[j].pos],q[j].x+q[j].y-query(q[j].y));
        tmp[k++]=q[j++];
      }
      for(j=l;j<=r;j++)  q[j]=tmp[j];  
    }
    int main()
    {
      //freopen("a.in","r",stdin);
      n=R();m=R();int x,y,t;
      for(int i=1;i<=n;i++) 
      {
        x=R()+1,y=R()+1;
        a[++tot].id=i,a[tot].x=x,a[tot].y=y;
        maxx=max(maxx,x),maxy=max(maxy,y);
      }
      for(int i=1;i<=m;i++)
      {
        t=R(),x=R()+1,y=R()+1;  
        if(t==1)
          a[++tot].id=tot,a[tot].x=x,a[tot].y=y;
        else 
          a[++tot].id=tot,a[tot].x=x,a[tot].y=y,a[tot].pos=++cnt;
        maxx=max(maxx,x),maxy=max(maxy,y);
      }
      maxx++,maxy++;
      for(int i=1;i<=cnt;i++)  ans[i]=1e+8;
      for(int i=1;i<=tot;i++)  q[i]=a[i];  //第一次,不用翻转 
        solve(1,tot);
      for(int i=1;i<=tot;i++)  q[i]=a[i],q[i].x=maxx-a[i].x;  //第一次翻转 (不一定是90度,把所有情况讨论了就行) 
        solve(1,tot);
      for(int i=1;i<=tot;i++)  q[i]=a[i],q[i].y=maxy-a[i].y;  //第二次翻转 
        solve(1,tot);
      for(int i=1;i<=tot;i++)  q[i]=a[i],q[i].x=maxx-a[i].x,q[i].y=maxy-a[i].y;  //第三次翻转 
        solve(1,tot);
      for(int i=1;i<=cnt;i++)  printf("%d
    ",ans[i]);
      return 0;
    }
  • 相关阅读:
    文件限额
    Shell命令
    HDFS基本概念
    hadoop学习
    CentOS 5.6怎么安装MongoDB数据库?
    RHEL/CentOS 6.x使用EPEL6与remi的yum源安装MySQL 5.5.x
    centos6.x yum 安装 mysql5.6 mysql5.7
    Centos6.4环境下DNS服务器的搭建
    CentOS系统中使用iptables设置端口转发
    通过WEB网管登录
  • 原文地址:https://www.cnblogs.com/AseanA/p/7525056.html
Copyright © 2011-2022 走看看