P4169 [Violet]天使玩偶/SJY摆棋子

CDQ分治的题目.

我们发现题目要我们求的\(|A_x-B_x|+|A_y-B_y|\)的绝对值号比较恶心.

试想一下怎么去掉

如果所有的点都在我们当前求的点的左下方(就是只考虑在他坐下方的点对他的贡献). 我们怎么求?

那么就要我们求\(min{A_x-B_x+A_y-B_y}\)(假设\(A\)为询问的点)

那么其实就是让我们求\(A_x+A_y-max(B_x+B_y)\)

也因为要满足左下角的限制

其实就是满足

\(B_x<=A_x\)同时满足\(B_y<=A_y\)中最大的\(B_x+B_y\)

这个是可以直接CDQ的

但是我们只考虑了左下方的点对他的贡献,很明显,这是不够的

那么我们就想办法依次将左上,右上,右下全部转化为左下

就是通过同最大值域的加减来改变他们的左边但不改变相对关系

注意常数就好了

另外,这种情况下归并排序的时间复杂度比快排优秀太多了

#include<bits/stdc++.h>
using namespace std;
const int N = 6e5 + 3;
const int M = 1e6 + 3;
const int INF = 2e9;
int n,m;
int max_x,max_y;
int ans[N];
struct Q{
int type;
int id;
int xi;
int yi;
int ans;
}q[N],p[N],h[N];
Q g[N];
struct BIT{
int c[M];
inline void ins(int x,int v){
for(;x <= max_y;x += x & -x) c[x] = max(c[x],v);
}
inline int query(int x){
int res = 0;
for(;x;x -= x & -x) res = max(res,c[x]);
return res;
}
inline void clear(int x){
for(;x <= max_y;x += x & -x) c[x] = 0;
}
}T;
int xx[N],yy[N];
inline bool cmp1(Q x,Q y){
return x.id < y.id;
}
inline bool cmp2(Q x,Q y){
if(x.xi != y.xi)
return x.xi < y.xi;
return x.yi < y.yi;
}
inline int read(){
int x = 0;int flag = 0;
char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') flag = 1;
ch = getchar();
}
while(isdigit(ch)){
x = (x<<1) + (x<<3) + (ch^'0');
ch = getchar();
}
if(flag) x = -x;
return x;
}
inline void solve(int l,int r){
if(l == r) return;
int mid = (l + r) >> 1;
solve(l,mid);solve(mid + 1,r);
//sort(p + l,p + mid + 1,cmp2);
//sort(p + mid + 1,p + r + 1,cmp2);
// nj printf("%d %d\n",l,r);
int now = l;
int ll = l,rr = mid + 1,nn = l - 1; // cout << 1 << endl;
for(int i = mid + 1;i <= r;++i){
while(i <= r && p[i].type != 2) ++i;
if(i > r) break;
for(;now <= mid && p[now].xi <= p[i].xi;++now) if(p[now].type == 1) T.ins(p[now].yi,p[now].xi + p[now].yi);
int t = T.query(p[i].yi);
if(t) ans[p[i].id] = min(ans[p[i].id],p[i].xi + p[i].yi - t);
}
for(int i = l;i < now;++i) if(p[i].type == 1) T.clear(p[i].yi);
while(ll <= mid && rr <= r){
if(p[ll].xi <= p[rr].xi) h[++nn] = p[ll++];
else h[++nn] = p[rr++];
}
while(ll <= mid) h[++nn] = p[ll++];
while(rr <= r) h[++nn] = p[rr++];
for(int i = l;i <= r;++i) p[i] = h[i];
}
inline void del(){
int rx = 0,ry = 0;m = 0;
for(int i = 1;i <= n;++i)
if(p[i].type == 1) rx = max(p[i].xi,rx),ry = max(p[i].yi,ry);
for(int i = 1;i <= n;++i){
if((p[i].xi <= rx && p[i].yi <= ry) || p[i].type == 2) g[++m] = p[i];
}
for(int i = 1;i <= m;++i) p[i] = g[i];
}
int main(){
n = read(),m = read();
for(int i = 1;i <= n;++i){
q[i].xi = read() + 1,q[i].yi = read() + 1;
max_x = max(max_x,q[i].xi),max_y = max(max_y,q[i].yi);
q[i].id = i;
q[i].type = 1;
}
for(int i = 1;i <= m;++i){
q[n + i].type = read();q[n + i].xi = read() + 1;q[n + i].yi = read() + 1;
q[n + i].id = i + n;
max_x = max(max_x,q[n + i].xi),max_y = max(max_y,q[n + i].yi);
}
n += m;
for(int i = 1;i <= n;++i) p[i] = q[i];
for(int i = 1;i <= n;++i) ans[i] = INF;
max_y = max(max_x,max_y) + 1;
solve(1,n);
for(int i = 1;i <= n;++i) p[i] = q[i],p[i].xi = max_y - p[i].xi;
solve(1,n);
for(int i = 1;i <= n;++i) p[i] = q[i],p[i].yi = max_y - p[i].yi;
solve(1,n);
for(int i = 1;i <= n;++i) p[i] = q[i],p[i].xi = max_y - p[i].xi,p[i].yi = max_y - p[i].yi;
solve(1,n);
for(int i = 1;i <= n;++i) if(ans[i] != INF) printf("%d\n",ans[i]);
return 0;
}

最新文章

  1. 使用 Ghost 写博客
  2. Tiny Mapper
  3. java web学习总结(九) -------------------通过Servlet生成验证码图片
  4. 跟着视频做的SSH项目总结
  5. jQuery官方基础教程笔记(转载)
  6. u-boot移植总结(一)start.S分析
  7. 向Oracle中传入数组,批量执行SQL语句
  8. Prepared Java infrastructure for distributed scenarios
  9. 【转】delphi 保存到txt文件
  10. C# DataRow[]转换DataTable
  11. SQL Server 2014 HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING 等待
  12. WinCE中断结构分析
  13. Javascript我学之四作用域
  14. ssh无秘钥登录
  15. Java-01-问题解答
  16. 2.编写实现:有一个三角形类Triangle,成员变量有底边x和另一条边y,和两边的夹角a(0&lt;a&lt;180),a为静态成员,成员方法有两个:求面积s(无参数)和修改角度(参数为角度)。 编写实现: 构造函数为 Triangle(int xx,int yy,int aa) 参数分别为x,y,a赋值 在main方法中构造两个对象,求出其面积,然后使用修改角度的方法,修改两边的夹角,再求出面积值。(提示
  17. Java基础-引用数据类型之集合(Collection)
  18. 【BZOJ3894】文理分科(最小割)
  19. php基础语法(数据类型、运算符)
  20. Spring事务不起作用原因

热门文章

  1. 外贸电子商务网站之Prestashop 语言包安装
  2. SFINAE and enable_if
  3. 集合 Enumerable Enumerator yield
  4. 【NS2】Installing ns-2.29 in Ubuntu 12.04
  5. poj 3225 【线段树】
  6. ERROR: epmd error for host &quot;yourhostname&quot;: timeout
  7. @NOIP2018 - D2T1@ 旅行
  8. Flask学习之一 hello world
  9. AspNetPager 样式
  10. oracle函数 sysdate