首页 > 其他分享 >[博客迁移20190713]题解 P4169 【[Violet]天使玩偶/SJY摆棋子】

[博客迁移20190713]题解 P4169 【[Violet]天使玩偶/SJY摆棋子】

时间:2024-05-27 21:34:39浏览次数:9  
标签:opt SJY return 20190713 int 题解 void mid inline

《算法竞赛》书上例题(可惜原书没代码

天使玩偶,一道好题。(书p243)我就来谈谈自己的想法吧!

而总有人在这种明明可以离线处理的三维偏序问题上投机取巧。

如:KDtree。 蒟蒻想说,KDtree在这题复杂度是不对的。虽有剪枝,可是还是有可能遍历整棵树的(期望复杂度不靠谱

对上述看法有争议的,请跳转KDtree讨论。觉得自己KDtree复杂度优美的,可以试试这个天使玩偶hack版,对此感谢qqvq大佬的hack数据。

而cdq分治 + bit(树状数组)只要两个log,何乐而不为呢~

cdq不会?三维偏序没学过?树状数组不会用?

那你还是去自闭吧,可以AFO了

开个玩笑,请左转一位大佬博客cdq分治入门到精通

好,那关于这道题,我想说:

先考虑简化版——即不带修改操作

对于每个点,其实是需找左上,左下,右上,右下四个方向最近距离,再取min。

以左下为例:min(1 <= i <= n) {(x - xi) + (y - yi)}

即 x + y - max(1 <= i <= n) {xi + yi} (xi <= x, yi <= y)

四方向类比,用bit维护即可。

考虑待修改,只需再按时间分治。用cdq分治,考虑修改操作在时间轴上对查询操作的影响即可:

cdq:

class rec {
public:
	int x, y, z;
	inline void Init(int _z, int _x, int _y) {
		x = _x; y = _y; z = _z; return;
	}
	inline bool operator < (const rec&opt) {
		return x < opt.x || x == opt.x && y < opt.y;
	}
} a[u], b[u];

int tot = 0;
int ans[u], n, m, t;

class BIT {
public:
	int c[u];
	inline void setup(void) {
		Ms(c, 0xcf); return;
	}
	
	inline int query(int x) {
		int y = inf;
		for (; x; x -= lowbit(x)) y = max(y, c[x]);
		return y;
	}
	
	inline void update(int x, int y) {
		for (; x < tot; x += lowbit(x))
			chkmax(c[x], y); return;
	}
	
	inline void modify(int x) {
		for (; x < tot; x += lowbit(x))
			c[x] = inf; return;
	}
} bit;

inline void calc(int st, int ed, int de, int dx, int dy) {
	for (register int i = st; i ^ ed; i += de) {
		int y = dy == 1 ? b[i].y : tot - b[i].y;
		int tmp = dx * b[i].x + dy * b[i].y;
		if (a[b[i].z].z == 1) bit.update(y, tmp);
		else chkmin(ans[b[i].z], abs(tmp - bit.query(y)));
	}
	
	for (register int i = st; i ^ ed; i += de) {
		int y = dy == 1 ? b[i].y : tot - b[i].y;
		if (a[b[i].z].z == 1) bit.modify(y);
	}
}

inline void cdqdiv(int l, int r) {
	int mid = l + r >> 1;
	if (l < mid) cdqdiv(l, mid);
	if (mid + 1 < r) cdqdiv(mid + 1, r);
	t = 0;
	for (register int i = l; i <= r; i++)
		if (i <= mid && a[i].z == 1 || i > mid && a[i].z == 2)
			b[++t] = a[i], b[t].z = i;

	sort(b + 1, b + t + 1);
	calc(1, t + 1, 1, 1, 1), calc(t, 0, -1, -1, -1);
	calc(1, t + 1, 1, 1, -1), calc(t, 0, -1, -1, 1);
}

全部代码(参考李煜东光盘)如下

CODE:

//Program written by Liu Zhaozhou ~~~
#include <bits/stdc++.h>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <deque>
#include <string>

#define lowbit(x) x & -x

#pragma GCC optimize(3)

using namespace std;

namespace Base {
inline char gc(void)
{
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

#define gc() getchar()

template <class T> inline void read(T &x)
{
	T flag = 1; x = 0; register char ch = gc();
	for (; !isdigit(ch); ch = gc()) if (ch == '-') flag = -1;
	for (; isdigit(ch); ch = gc()) x = (x << 1) + (x << 3) + (ch & 15);
	x *= flag; return;
}

inline int init(void) {
	int x; read(x); return x;
}

template <class T> inline void write(T x) {
	if (x < 0) putchar('-'), x = -x;
	register T y = 1; int len = 1;
	for (; y <= x / 10; y *= 10) ++len;
	for (; len; --len, x %= y, y /= 10) putchar(x / y + 48);
}

template <class T> inline void writeln(T x) {write(x); puts("");}
template <class T> inline void writeln(T x, char c) {write(x); putchar(c);}
template <class T> inline void writeln(char c, T x) {putchar(c); write(x);}

template <class T> inline void chkmax(T &x, const T y) {x > y ? x = x : x = y;}
template <class T> inline void chkmin(T &x, const T y) {x < y ? x = x : x = y;}

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

#define Ms(arr, opt) memset(arr, opt, sizeof(arr))
#define Mp(x, y) make_pair(x, y)

inline void file(string str) {
	freopen((str + ".in").c_str(), "r", stdin);
	freopen((str + ".out").c_str(), "w", stdout);
}
}

using namespace Base;

namespace CDQsolution {

enum {
	u = 1000010,
	inf = -114783648
};

class rec {
public:
	int x, y, z;
	inline void Init(int _z, int _x, int _y) {
		x = _x; y = _y; z = _z; return;
	}
	inline bool operator < (const rec&opt) {
		return x < opt.x || x == opt.x && y < opt.y;
	}
} a[u], b[u];

int tot = 0;
int ans[u], n, m, t;

class BIT {
public:
	int c[u];
	inline void setup(void) {
		Ms(c, 0xcf); return;
	}
	
	inline int query(int x) {
		int y = inf;
		for (; x; x -= lowbit(x)) y = max(y, c[x]);
		return y;
	}
	
	inline void update(int x, int y) {
		for (; x < tot; x += lowbit(x))
			chkmax(c[x], y); return;
	}
	
	inline void modify(int x) {
		for (; x < tot; x += lowbit(x))
			c[x] = inf; return;
	}
} bit;

inline void calc(int st, int ed, int de, int dx, int dy) {
	for (register int i = st; i ^ ed; i += de) {
		int y = dy == 1 ? b[i].y : tot - b[i].y;
		int tmp = dx * b[i].x + dy * b[i].y;
		if (a[b[i].z].z == 1) bit.update(y, tmp);
		else chkmin(ans[b[i].z], abs(tmp - bit.query(y)));
	}
	
	for (register int i = st; i ^ ed; i += de) {
		int y = dy == 1 ? b[i].y : tot - b[i].y;
		if (a[b[i].z].z == 1) bit.modify(y);
	}
}

inline void cdqdiv(int l, int r) {
	int mid = l + r >> 1;
	if (l < mid) cdqdiv(l, mid);
	if (mid + 1 < r) cdqdiv(mid + 1, r);
	t = 0;
	for (register int i = l; i <= r; i++)
		if (i <= mid && a[i].z == 1 || i > mid && a[i].z == 2)
			b[++t] = a[i], b[t].z = i;

	sort(b + 1, b + t + 1);
	calc(1, t + 1, 1, 1, 1), calc(t, 0, -1, -1, -1);
	calc(1, t + 1, 1, 1, -1), calc(t, 0, -1, -1, 1);
}

}

using namespace CDQsolution;

signed main(void) {
	file("cdq");
	read(n); read(m); m += n;
	for (int i = 1; i <= n; i++)
		read(a[i].x), read(a[i].y), a[i].y++, a[i].z = 1;
	for (int i = n + 1; i <= m; i++)
		read(a[i].z), read(a[i].x), read(a[i].y), a[i].y++;

	for (int i = 1; i <= m; i++)
		chkmax(tot, a[i].y);
	tot++; bit.setup(); Ms(ans, 0x3f);
	cdqdiv(1, m);
	for (int i = 1; i <= m; i++)
		if (a[i].z == 2) writeln(ans[i]);
    return 0;
}

/*cdq*/


cdq大法吼,谢谢兹磁!!!

标签:opt,SJY,return,20190713,int,题解,void,mid,inline
From: https://www.cnblogs.com/EternalEpic/p/18216566

相关文章

  • QT | 文件读写过程中丢失的 OD OA 问题解决
    今天发现QT以文本方式(QIODevice::Text)写入二进制0x0A会出现问题,写入的是一个字节(实际应该是两个字节),结果在Zed上看,显示是2个字节。明显每个0x0A前都多了个0x0D,导致我的bin文件全部都错位了期望的效果应该是原来按照字节流的形式输出文本时,ofstream会自动将输......
  • Codeforces Round 927 (Div. 3) D. Card Game 题解 贪心
    CardGame题目描述Twoplayersareplayinganonlinecardgame.Thegameisplayedusinga32-carddeck.Eachcardhasasuitandarank.Therearefoursuits:clubs,diamonds,hearts,andspades.Wewillencodethemwithcharacters‘C’,‘D’,‘H’,......
  • 题解:CF1975G Zimpha Fan Club
    \(\text{Link}\)题意给你两个长度分别为\(n,m\)的字符串\(s,t\),其中仅包含小写字母、-和*,你需要将-替换为任意小写字母,*替换为任意小写字母构成的字符串(可以为空串),问是否可以使得\(s'=t'\)。\(n,m\le2\times10^6\),12s。思路首先我们有工具:NTT优化带通配符的字符......
  • 2024 CCPC 全国邀请赛(山东)暨山东省大学生程序设计竞赛题解 A C F I K
    超时就是AC队第一次打ccpc比较菜蒟蒻只能做五题ProblemA.打印机算法:二分思路:二分时间每次check查看当前时间内所有打印机可以打印的个数是否符合条件注意二分的右边界为2e18ProblemC.多彩的线段2算法:组合数思路:将所有线段按照起点从左到右排序枚举线段每次将当......
  • Codeforces Round #947 题解 (A~G)
    目录A.BazokaandMocha'sArrayB.378QAQandMocha'sArrayC.ChamoandMocha'sArrayD.PainttheTreeE.ChainQueriesF.SetG.ZimphaFanClubA.BazokaandMocha'sArray枚举每个循环移位判断.B.378QAQandMocha'sArray首先最小的数肯定得选,删掉最小的数的倍数......
  • 【leetcode 399 周赛】【题解】
    第一题和第三题一样。就是求约数第二题就是模拟第4题使用线段树1,3题代码实际上发现没有下面代码的负载,比如:a*b=n,枚举a就好,a在[1,sqrt(n)内。importjava.util.*;classSolution{publicintnumberOfPairs(int[]nums1,int[]nums2,intk){......
  • CATIA入门操作——萌新宝宝遇到的奇奇怪怪的问题解决,持续更新中。。。
    目录引出发生肾么事了??鼠标中键旋转不了解决:特征树不显示参数关系我的窗口去哪了?插曲:草图工具的调出插曲:颜色工具栏显示弹窗警告警告:创建约束是临时的操作技巧技巧:快速隐藏不相关元素工具栏怎么变成水平?总结异形弹簧新建几何体草图编辑,画一条样条线进行扫掠,圆心和半......
  • CF1821F Timber 题解
    题意:在\([1,n]\)的区间里放\(m\)棵树,每棵树的高度为\(k\)。求有多少种放置树的方法,满足:每个树都在整点上,且每个点最多只能放一棵树。存在一种砍倒树的方案,使得树倒了之后不会越界,也不会有某个点被超过一棵树占据。你可以自由选择树向左倒(也就是占据区间\([x-k,x]\))......
  • [SHOI2007]书柜的尺寸 题解
    题目链接设\(f_{i,t1,t2}\)表示前\(i\)本书,第一层的宽度为\(t1\),第二层的宽度为\(t2\),所需要的最小高度。第三层宽度\(t3=\sum_{i=1}^{i}t_i-t1-t2\)。但本题还有一个重要限制:每层的高度取决于该层最高的书,如果直接按照顺序加入书本,从\(dp\)的状态来看,无法确定新书本......
  • CCF-GESP 等级考试 2024年3月认证C++一级真题解析
    2024年03月真题1单选题第1题C++表达式(3-2)*3+5的值是()。A.-13B.8C.2D.0正确答案:B.8解析:首先计算括号中的表达式(3-2),得到(1)。接下来进行乘法运算(1*3),得到(3)。最后进行加法运算(3+5),得到(8)。因此,表达式的值是(8)。第2题C++......