这道好(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. VisualSVN Server 配置和使用

    以前使用官方Subversion搭建SVN版本控制环境,很繁琐.在Windows 系统上,要想让它随系统启动,就要封装SVN Server为windws service,还要通过修改配置文件来控制用户 ...

  2. Nginx配置WebService、MySQL、SQL Server、ORACLE等代理

    首先介绍一下Nginx的基本使用: 注意不要直接双击nginx.exe,这样会导致修改配置后重启.停止nginx无效,需要手动关闭任务管理器内的所有nginx进程 在nginx.exe目录,打开命令行 ...

  3. 【iCore4 双核心板_ARM】例程十二:通用定时器实验——定时点亮LED

    实验原理: 通过STM32的三个GPIO口来驱动LED灯的三个通道,设定GPIO为推挽输出模式,采 用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮,通过通用定时器TIM3 实现50 ...

  4. 【iCore1S 双核心板_ARM】例程十三:SDIO实验——读取SD卡信息

    实验现象: 核心代码: int main(void) { /* USER CODE BEGIN 1 */ HAL_SD_TransferStateTypedef State; /* USER CODE ...

  5. mac中安装wxpython

    一.简介 wxPython是Python语言的一套优秀的GUI图形库,允许Python程序员很方便的创建完整的.功能键全的GUI用户界面. wxPython是作为优秀的跨平台GUI库wxWidgets ...

  6. 【javascript】console 让 js 调试更简单

    浏览器的控制台(console)是最重要的面板,主要作用是显示网页加载过程中产生各类信息. 显示信息 console.log('hello world'); console.debug('debug' ...

  7. 解决:ngxin做http强制跳转https,接口的POST请求变成GET

    域名配置了http强制跳转htpps后发现app发起post请求会出现405错误. 所以怀疑是http强制跳转https出现了问题.修改nginx配置如下即可解决: server { listen ; ...

  8. hadoop 在centos中的搭建

    总体思路,准备主从服务器,配置主服务器可以无密码SSH登录从服务器,解压安装JDK,解压安装Hadoop,配置hdfs.mapreduce等主从关系. 1.环境,3台CentOS7,64位,Hadoo ...

  9. ORA-00257:archiver error问题处理方法

    原文链接:http://www.7747.net/database/201109/104615.html ORA-00257: archiver error. Connect internal onl ...

  10. 通过mysql写入php一句话木马

    利用mysql写入一句话木马 前提: root权限,知道了服务器的web的绝对路径 select "<?php @eval($_POST['pass']);?>" IN ...