这道好(du)题(liu)还是很不错的 挺锻炼代码能力和不断优化 卡常的能力的。

对于 每次询问 我都可以将其分出方向 然后 写 也就是针对于4个方向 左下 左上 右下 右上

这样的话 就成功转换了问题 求4次 三维偏序即可 水题啊。

然后 打完代码 就提交 T飞了

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<utility>
#include<queue>
#include<deque>
#include<vector>
#include<stack>
#include<algorithm>
#include<set>
#include<bitset>
#include<map>
#define INF 2147483646
#define ll long long
#define ldb long double
#define x(i) t[i].x
#define y(i) t[i].y
#define k(i) t[i].k
#define t(i) t[i].t
#define id(i) t[i].id
using namespace std;
char buf[<<],*ft,*fs;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
x<?x=-x,putchar('-'):;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar();return;
}
const int MAXN=,maxn=;
int n,m,tot,num,cnt;
struct wy
{
int x,y;
int t,k;
int id;
}t[MAXN<<],tmp[MAXN<<];
int ans[MAXN],c[maxn+];//树状数组维护前缀最大值!
//注意时间戳也得排序 我的思维漏洞!
int cmp(wy x,wy y)//左下
{
if(x.x==y.x&&x.y==x.y)return x.t<y.t;
return x.x==y.x?x.y<y.y:x.x<y.x;
}
int cmp1(wy x,wy y)//左上
{
if(x.x==y.x&&x.y==x.y)return x.t<y.t;
return x.x==y.x?x.y>y.y:x.x<y.x;
}
int cmp2(wy x,wy y)//右下
{
if(x.x==y.x&&x.y==x.y)return x.t<y.t;
return x.x==y.x?x.y<y.y:x.x>y.x;
}
int cmp3(wy x,wy y)//右上
{
if(x.x==y.x&&x.y==x.y)return x.t<y.t;
return x.x==y.x?x.y>y.y:x.x>y.x;
}
inline int max(int x,int y){return x>y?x:y;}
void add(int x,int y)
{
if(y==INF){for(;x<=maxn;x+=x&(-x))c[x]=-INF;return;}
for(;x<=maxn;x+=x&(-x))c[x]=max(c[x],y);
return;
}
inline int ask(int x)
{
int sum=-INF;
for(;x;x-=x&(-x))sum=max(sum,c[x]);
return sum;
}
void CDQ(int l,int r,int p)
{
if(l==r)return;
int mid=(l+r)>>;
CDQ(l,mid,p);
CDQ(mid+,r,p);
int i=l,j=mid+;
if(p==)
{
for(int k=l;k<=r;++k)
{
if(j>r||(i<=mid&&t(i)<=t(j)))
{
if(k(i)!=)add(y(i),x(i)+y(i));
tmp[k]=t[i];
++i;
}
else
{
if(k(j)==){tmp[k]=t[j];++j;continue;}
//if(id(j)==1)cout<<x(j)<<' '<<y(j)<<endl;
int maxx=ask(y(j));
if(maxx==-INF){tmp[k]=t[j];++j;continue;}
ans[id(j)]=min(ans[id(j)],y(j)+x(j)-maxx);
tmp[k]=t[j];
++j;
}
}
for(int k=l;k<=r;k++)
{
if(k<=mid&&k(k)!=)add(y(k),INF);
t[k]=tmp[k];
}
}
else
{
for(int k=l;k<=r;++k)
{
if(j>r||(i<=mid&&t(i)<=t(j)))
{
if(k(i)!=)add(maxn-y(i),x(i)-y(i));
tmp[k]=t[i];
++i;
}
else
{
if(k(j)==){tmp[k]=t[j];++j;continue;}
int maxx=ask(maxn-y(j));
if(maxx==-INF){tmp[k]=t[j];++j;continue;}
//cout<<maxx<<endl;
ans[id(j)]=min(ans[id(j)],x(j)-y(j)-maxx);
tmp[k]=t[j];
++j;
}
}
for(int k=l;k<=r;k++)
{
if(k<=mid&&k(k)!=)add(maxn-y(k),INF);
t[k]=tmp[k];
}
}
return;
}
void CDQ1(int l,int r,int p)
{
if(l==r)return;
int mid=(l+r)>>;
CDQ1(l,mid,p);
CDQ1(mid+,r,p);
int i=l,j=mid+;
if(p==)
{
for(int k=l;k<=r;++k)
{
if(j>r||(i<=mid&&t(i)<=t(j)))
{
if(k(i)!=)add(y(i),y(i)-x(i));
tmp[k]=t[i];
++i;
}
else
{
if(k(j)==){tmp[k]=t[j];++j;continue;}
//if(id(j)==1)cout<<x(j)<<' '<<y(j)<<endl;
int maxx=ask(y(j));
if(maxx==-INF){tmp[k]=t[j];++j;continue;}
ans[id(j)]=min(ans[id(j)],y(j)-x(j)-maxx);
tmp[k]=t[j];
++j;
}
}
for(int k=l;k<=r;k++)
{
if(k<=mid&&k(k)!=)add(y(k),INF);
t[k]=tmp[k];
}
}
else
{
for(int k=l;k<=r;++k)
{
if(j>r||(i<=mid&&t(i)<=t(j)))
{
if(k(i)!=)add(maxn-y(i),-x(i)-y(i));//此处不要想当然的写
tmp[k]=t[i];
++i;
}
else
{
if(k(j)==){tmp[k]=t[j];++j;continue;}
int maxx=ask(maxn-y(j));
if(maxx==-INF){tmp[k]=t[j];++j;continue;}
ans[id(j)]=min(ans[id(j)],-maxx-x(j)-y(j));//变形要正确啊!
tmp[k]=t[j];
++j;
}
}
for(int k=l;k<=r;k++)
{
if(k<=mid&&k(k)!=)add(maxn-y(k),INF);
t[k]=tmp[k];
}
}
return;
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
memset(ans,,sizeof(ans));
n=read();m=read();num=n;
for(int i=;i<=n;i++)x(i)=read(),y(i)=read();
for(int i=;i<=m;i++)
{
int p=read();
x(++num)=read();y(num)=read();
if(p==)k(num)=,id(num)=++cnt;
t(num)=++tot;
}
//for(int i=1;i<=num;i++)cout<<x(i)<<' '<<y(i)<<' '<<t(i)<<' '<<k(i)<<endl;
for(int i=;i<=maxn;i++)c[i]=-INF;
sort(t+,t++num,cmp);//左下
CDQ(,num,);//左下
//for(int i=1;i<=cnt;i++)cout<<ans[i]<<endl;
for(int i=;i<=maxn;i++)c[i]=-INF;
sort(t+,t++num,cmp1);//左上
CDQ(,num,);//左上
//for(int i=1;i<=cnt;i++)cout<<ans[i]<<endl;
for(int i=;i<=maxn;i++)c[i]=-INF;
sort(t+,t++num,cmp2);//右下
CDQ1(,num,);//右下
//for(int i=1;i<=cnt;i++)cout<<ans[i]<<endl;
for(int i=;i<=maxn;i++)c[i]=-INF;
sort(t+,t++num,cmp3);//右上
CDQ1(,num,);//右上
//for(int i=1;i<=cnt;i++)cout<<ans[i]<<endl;
for(int i=;i<=cnt;i++)put(ans[i]);
return ;
}

都别管我我要写4次CDQ 我要sort 4次然后不出意料只拿到50分。

原因是sort的次数多了 常数是别人的近乎4倍 (有的人一次sort都不做 按照时间直接排)

然后脑残的写了这么段代码 一直T 照着书上的 标程改了一下是一种比较简洁的做法。

但是其CDQ的每层都需要sort 一下比较浪费时间但是还是能拿到60分的 开O2 能A呢。

然后学了一下书上的做法 发现真心简单 代码复杂度 时间复杂度 空间复杂度包括常数都远远低于我

// luogu-judger-enable-o2
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<utility>
#include<queue>
#include<deque>
#include<vector>
#include<stack>
#include<algorithm>
#include<set>
#include<bitset>
#include<map>
#define INF 2147483646
#define ll long long
#define ldb long double
#define x(i) t[i].x
#define y(i) t[i].y
#define t(i) t[i].t
#define id(i) t[i].id
using namespace std;
char buf[<<],*ft,*fs;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
x<?x=-x,putchar('-'):;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar();return;
}
const int MAXN=,maxn=;
int n,m,cnt,num,tot,h;
int ans[MAXN],c[maxn],maxx;
struct wy
{
int x,y;
int t;
int id;
friend int operator <(const wy &a,const wy &b)
{
return a.x==b.x?a.y<b.y:a.x<b.x;//此时排序不用时间戳(经过实验
//考虑一次CDQ 分治 时间复杂度 ≈(n+m)*log(n+m)^3左右
}
}t[MAXN],tmp[MAXN];
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x>y?y:x;}
inline void add(int x,int y){for(;x<=maxx;x+=x&(-x))c[x]=max(c[x],y);}
inline int abs(int x){return x<?-x:x;}
inline int ask(int x)
{
int maxx1=-INF;
for(;x;x-=x&(-x))maxx1=max(maxx1,c[x]);
return maxx1;
}
inline void remove1(int x)
{
for(;x<=maxx;x+=x&(-x))c[x]=-INF;
return;
}
void calculate(int st,int en,int w,int kx,int ky)//属性
{
for(int i=st;i!=en;i+=w)
{
int yy=(ky==?tmp[i].y:maxx-tmp[i].y);
int sum=kx*tmp[i].x+ky*tmp[i].y;
if(tmp[i].t==)add(yy,sum);
else
{
int an=ask(yy);
if(an==-INF)continue;
ans[tmp[i].id]=min(ans[tmp[i].id],sum-an);
}
//if(tmp[i].id==2)cout<<sum<<' '<<ask(yy)<<endl;
}
for(int i=st;i!=en;i+=w)if(tmp[i].t==)remove1(ky==?tmp[i].y:maxx-tmp[i].y);
}
void CDQ(int l,int r)
{
int mid=(l+r)>>;
if(l<mid)CDQ(l,mid);
if(mid+<r)CDQ(mid+,r);
h=;
for(int i=l;i<=r;i++)if((i<=mid&&t[i].t==)||(i>mid&&t[i].t==))tmp[++h]=t[i];
sort(tmp+,tmp++h);
calculate(,h+,,,);//左下
calculate(,h+,,,-);//左上
calculate(h,,-,-,);//右下
calculate(h,,-,-,-);//右上
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=read();m=read();num=n;
for(int i=;i<=n;++i)
{
x(i)=read();
y(i)=read();
t(i)=;
maxx=max(maxx,y(i));
}
for(int i=;i<=m;++i)
{
t(++num)=read();
x(num)=read();
y(num)=read();
id(num)=t(num)==?++cnt:;
maxx=max(maxx,y(num));
}
//put(cnt);
++maxx;//巧妙一招
for(int i=;i<=maxx;++i)c[i]=-INF;
memset(ans,,sizeof(ans));
CDQ(,num);
for(int i=;i<=cnt;i++)put(ans[i]);
return ;
}

比较难受 因为这浪费了我很多的时间 然后最后还是T 开了O2 死T一个点(原因是 我是个NC啊。。。

开O2 过了不算什么我要不开O2 过

点开题解发现我的第一个代码的思想及其接近其 题解中跑的最快的。

所以发现可以不用sort 于是顺利不开O2 第一个代码顺利得到80分。

发现可以加一个优化是 能不加到树状数组里就不加 到需要的时候再加 还有一些卡常的东西

最终不开O2 直接A (一直T的那个点是因为下标为0 树状数组原地GG了。。。)

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<utility>
#include<queue>
#include<deque>
#include<vector>
#include<stack>
#include<algorithm>
#include<set>
#include<bitset>
#include<map>
#define INF 2147483646
#define ll long long
#define ldb long double
#define x(i) t[i].x
#define y(i) t[i].y
#define k(i) t[i].k
#define t(i) t[i].t
#define id(i) t[i].id
#define R register
using namespace std;
//char buf[1<<15],*ft,*fs;
//inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void put(int x)
{
x<?x=-x,putchar('-'):;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar();return;
}
const int maxn=;
int n,m,tot,num,cnt,maxx1,maxx2;
struct wy
{
int x,y;
int k,id;
inline bool operator <(const wy &w)const
{
return x<w.x;
}
}t[maxn],tmp[maxn],a[maxn];
int ans[maxn],c[maxn+];
inline int max(int x,int y){return x>y?x:y;}
inline void add(int x,int y)
{ for(;x<=maxx1;x+=x&(-x))
{
if(c[x]>y)break;
else c[x]=y;
}
return;
}
inline void remove1(int x)
{
for(;x<=maxx1;x+=x&(-x))if(c[x])c[x]=;
return;
}
inline int ask(int x)
{
int sum=-INF;
for(;x;x-=x&(-x))sum=max(sum,c[x]);
return sum;
}
inline void CDQ(int l,int r)
{
int mid=(l+r)>>;
if(l<mid)CDQ(l,mid);
if(r>mid+)CDQ(mid+,r);
R int i=l,j=mid+;
for(j=mid+;j<=r;j++)
{
if(k(j)==)
{
for(;i<=mid&&x(i)<=x(j);i++)
if(k(i)==)add(y(i),x(i)+y(i));
int maxx=ask(y(j));
maxx==?:ans[id(j)]=min(ans[id(j)],y(j)+x(j)-maxx); }
}
for(j=l;j<i;j++)if(k(j)==)remove1(y(j));
i=l,j=mid+;
for(R int k=l;k<=r;++k)
{
if(j>r||(i<=mid&&t[i]<t[j]))tmp[k]=t[i],++i;
else tmp[k]=t[j],++j;
}
for(R int k=l;k<=r;++k)t[k]=tmp[k];
return;
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=read();m=read();num=n;
for(R int i=;i<=n;++i){x(i)=read()+,y(i)=read()+;maxx1=max(maxx1,y(i));maxx2=max(maxx2,x(i));}
for(R int i=;i<=m;++i)
{
int p=read();
x(++num)=read()+;y(num)=read()+;
if(p==)k(num)=,id(num)=++cnt;
maxx1=max(maxx1,y(num));
maxx2=max(maxx2,x(num));
}
++maxx1;++maxx2;
for(R int i=;i<=cnt;++i)ans[i]=INF;
for(R int i=;i<=num;++i)a[i]=t[i];
CDQ(,num);//左下
for(R int i=;i<=num;++i)t[i]=a[i],y(i)=maxx1-y(i);
CDQ(,num);//左上
for(R int i=;i<=num;++i)t[i]=a[i],x(i)=maxx2-x(i);
CDQ(,num);//右下
for(R int i=;i<=num;++i)t[i]=a[i],x(i)=maxx2-x(i),y(i)=maxx1-y(i);
CDQ(,num);//右上
for(R int i=;i<=cnt;++i)put(ans[i]);
return ;
}

当然 为了能够完美的A掉这道题 我决定去学一个更强的东西 KD-tree.

然后在抄了20min代码后觉定放弃 尧神说没多大卵用。。。

所以这篇博文到此啦,关键是不断优化的思想 少开O2

天使玩偶:CDQ分治的更多相关文章

  1. [BZOJ2716] [Violet 3]天使玩偶(CDQ分治)

    [BZOJ2716] [Violet 3]天使玩偶(CDQ分治) 题面 Ayu 在七年前曾经收到过一个天使玩偶,当时她把它当作时间囊埋在了地下.而七年后 的今天,Ayu 却忘了她把天使玩偶埋在了哪里, ...

  2. BZOJ 2716: [Violet 3]天使玩偶( CDQ分治 + 树状数组 )

    先cdq分治, 然后要处理点对答案的贡献, 可以以询问点为中心分成4个区域, 然后去掉绝对值(4种情况讨论), 用BIT维护就行了. --------------------------------- ...

  3. [bzoj] 2716 天使玩偶 || CDQ分治

    原题 已知n个点有天使玩偶,有m次操作: 操作1:想起来某个位置有一个天使玩偶 操作2:询问离当前点最近的天使玩偶的曼哈顿距离 显然的CDQ问题,三维分别为时间,x轴,y轴. 但是这道题的问题在于最近 ...

  4. BZOJ 2716 Violet 3 天使玩偶 CDQ分治

    题目大意:初始给定平面上的一个点集.提供两种操作: 1.将一个点增加点集 2.查询距离一个点最小的曼哈顿距离 K-D树是啥...不会写... 我仅仅会CDQ分治 对于一个询问,查询的点与这个点的位置关 ...

  5. 洛谷P4169 天使玩偶 CDQ分治

    还是照着CDQ的思路来. 但是有一些改动: 要求4个方向的,但是可爱的CDQ分治只能求在自己一个角落方向上的.怎么办?旋转!做4次就好了. 统计的不是和,而是——max!理由如下: 设当前点是(x,y ...

  6. CH 4701 - 天使玩偶 - [CDQ分治]

    题目链接:传送门 关于CDQ分治(参考李煜东<算法竞赛进阶指南>): 对于一系列操作,其中的任何一个询问操作,其结果必然等价于:初始值 + 此前所有的修改操作产生的影响. 假设共有 $m$ ...

  7. BZOJ.2716.[Violet3]天使玩偶(CDQ分治 坐标变换)

    题目链接 考虑对于两个点a,b,距离为|x[a]-x[b]|+|y[a]-y[b]|,如果a在b的右上,那我们可以把绝对值去掉,即x[a]+y[a]-(x[b]+y[b]). 即我们要求满足x[b]& ...

  8. BZOJ 2716 [Violet 3]天使玩偶 (CDQ分治、树状数组)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2716 怎么KD树跑得都那么快啊..我写的CDQ分治被暴虐 做四遍CDQ分治,每次求一个 ...

  9. 洛谷P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治)

    [Violet]天使玩偶/SJY摆棋子 题目传送门 解题思路 用CDQ分治开了氧气跑过. 将输入给的顺序作为第一维的时间,x为第二维,y为第三维.对于距离一个询问(ax,ay),将询问分为四块,左上, ...

随机推荐

  1. MXNET:深度学习计算-模型参数

    我们将深入讲解模型参数的访问和初始化,以及如何在多个层之间共享同一份参数. 之前我们一直在使用默认的初始函数,net.initialize(). from mxnet import init, nd ...

  2. Centos 6.4 安装dnsmasq

    1 下载源码 wget http://www.thekelleys.org.uk/dnsmasq/dnsmasq-2.45.tar.gz cp dnsmasq-2.45.tar.gz /usr/src ...

  3. CentOs 6.x 升级 Python 版本【转】

    在CentOS 6.X 上面安装 Python 2.7.X CentOS 6.X 自带的python版本是 2.6 , 由于工作需要,很多时候需要2.7版本.所以需要进行版本升级.由于一些系统工具和服 ...

  4. linux下依赖库的版本问题引起的安装失败:libssl-dev版本问题无法安装 :libssl-dev : 依赖: libssl1.0.0 (= 1.0.1-4ubuntu3) 但是 1.0.1-4ubuntu5.31 正要被安装

    依赖库版本问题引起的安装失败解决方法如下有两种: 1.是由于源需要更新,如下操作: libssl-dev : 依赖: libssl0.9.8 (= 0.9.8o-1ubuntu4) 但是 0.9.8o ...

  5. Virtualbox的centos7 nat和桥接网络配置

    在实际配置虚拟机的过程中,网络配置时候一个很繁琐的过程,经常一个点没注意到,就访问不了了.在此,做一个简单的教程以供后续使用时可以参考! 方法一: 使用NAT网络 1. 选择网卡 安装centos7的 ...

  6. python日志,一个改版SMTPHandler

    1.官方logging包的SMTPHandler不支持ssl的邮箱,修改成兼容ssl以支持大部分国内邮箱. 2.增加一个频率控制的参数,比如要设置一个报警邮件,异常时候通知我们,但假设1分钟内异常几千 ...

  7. [UI] 03 - Bootstrap: component

    前言 一.框架体系 Bootstrap 是基于 HTML5.CSS3.JAVASCRIPT. 教程被分为: Bootstrap 基本结构. Bootstrap CSS. Bootstrap 布局组件 ...

  8. 九度OJ 1067 n的阶乘 (模拟)

    题目1067:n的阶乘 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5666 解决:2141 题目描写叙述: 输入一个整数n,输出n的阶乘 输入: 一个整数n(1<=n<=2 ...

  9. python中getcwd()方法慎用

    比如我们想要获取当前目录的路径,有人可能会用到getcwd()方法,但是会发现这个方法有时候不好用.下面介绍一下,getcwd()方法的具体细节: 1.os.getcwd():获取当前工作目录,也就是 ...

  10. sklearn数据预处理

    一.standardization 之所以标准化的原因是,如果数据集中的某个特征的取值不服从标准的正太分布,则性能就会变得很差 ①函数scale提供了快速和简单的方法在单个数组形式的数据集上来执行标准 ...