首页 > 其他分享 >[UR #13 B] Ernd

[UR #13 B] Ernd

时间:2023-07-14 10:36:26浏览次数:32  
标签:13 le int Ernd long UR i64 maxn id

这个感觉很离谱啊,我不是很会这个。

考虑 DP。根据 THUSC 的经验,这个 \(K\) 和坐标一定不能设进状态,我们考虑把它放到转移里考虑。

对于一个盘子,如果我们接住了它,那就确定了它的坐标,而且我们知道两个盘子间的距离,这样就解决了坐标。

对于 \(K\),我们考虑一个经典的 trick:分段转移。

发现可以互相到达的盘子是若干连续段,所以可以这样 DP:设 \(f_i\) 表示前 \(i\) 个盘子的最大贡献,那么 \(f_i=\max\limits_{j|j,i可以同时接住} \{(i-j+1)^2 + \max\limits_{k|k,j可以同时接住} f_k \}\)。

后面那个东西和 \(i\) 没关系,考虑把它设成 \(g_j\)。这样是 \(\mathcal O(n^2)\) 的。

在它这个状态转移上下功夫,我们发现 \(i,j(i\lt j)\) 可以同时接住的条件是 \(|a_i-a_j|\le b_j-b_i\),转化一下就是 \(a_i-a_j\le b_j-b_i\) 且 \(a_j-a_i\le b_j-b_i\),可以凑出一个相当漂亮的形式:\(a_i+b_i\le a_j+b_j, b_i-a_i\le b_j-a_j\)。

那么把 \((a_i + b_i, b_i - a_i)\) 看作平面上的点,这就是一个二维偏序问题,BIT 维护最大值即可。这样就解决了 \(g\) 的问题。

然后考虑 \(f\),这个平方的式子是一个经典的斜率优化的形式,用栈维护一个上凸包,在上面二分即可。

注意我们这个转移时基于 \(j\) 可以到达 \(i\) 的,这样划分为了若干连续段,所以我们对每个连续段都要单独开一个栈维护凸包。

关于 \(g\) 和 \(f\) 的互相影响,我们下意识地使用半在线的方法计算。但这是不必要的!观察到 \(i\to j\) 的连续段,\(a+b,b-a\) 一定都是单增的,所以 \(g\) 的转移顺序并不会受 \(f\) 的转系顺序影响,直接在一开始按 \(a+b\) 拍个序做就行了。

时间复杂度 \(\mathcal O(n\log n)\)。

Typora Github Theme 的代码块渲染怎么这么奇怪。这么不牛。

#include <bits/stdc++.h>
#define pb emplace_back
#define fir first
#define sec second

const int maxn = 5e5 + 5;
const long double eps = 1e-6;
using i64 = long long;
using ld = long double;

struct node {
	int x, y, id;
	node() {
		x = y = id = 0;
	}
	node(int x, int y, int id) : x(x), y(y), id(id) {}
} s[maxn];

int n, cnt, bel[maxn];
i64 c[maxn], f[maxn], g[maxn];

void chkmax(i64& x, i64 y) {
	if(y > x)
		x = y;
	return ;
}

int lowbit(int x) {
	return x & -x;
}

void add(int x, i64 y) {
	for(;x <= cnt;x += lowbit(x))
		chkmax(c[x], y);
	return ;
}

i64 query(int x) {
	i64 ans = 0;
	for(;x;x -= lowbit(x))
		chkmax(ans, c[x]);
	return ans;
}

i64 calc(int x) {
	return g[x] + 1ll * x * x - 2 * x;
}

ld slope(int x, int y) {
	return 1.0 * (calc(y) - calc(x)) / (y - x);
}

struct Stack {
	std::vector<int> q;
	void insert(int x) {
		while(q.size() > 1&&slope(q[q.size() - 2], q.back()) - slope(q.back(), x) <= -eps)
			q.pop_back();
		q.pb(x);
		return ;
	}
	int query(int x) {
		if(q.size() == 1)
			return q.back();
		int l = 0, r = q.size() - 2;
		while(l <= r) {
			int mid = (l + r) >> 1;
			if(slope(q[mid], q[mid + 1]) - 2.0 * x >= eps)
				l = mid + 1;
			else
				r = mid - 1;
		}
		return q[l];
	}
} stk[maxn];

int main() {
	scanf("%d", &n);
	for(int i = 1;i <= n;++ i) {
		int a, b;
		scanf("%d %d", &a, &b);
		c[++ cnt] = b - a;
		s[i] = node(a + b, b - a, i);
		bel[i] = bel[i - 1] + (s[i].x < s[i - 1].x||s[i].y < s[i - 1].y);
	}
	std::sort(c + 1, c + 1 + cnt);
	cnt = std::unique(c + 1, c + 1 + cnt) - c - 1;
	for(int i = 1;i <= n;++ i)
		s[i].y = std::lower_bound(c + 1, c + 1 + cnt, s[i].y) - c;
	for(int i = 1;i <= cnt;++ i)
		c[i] = 0;
	std::sort(s + 1, s + 1 + n, [&](const node& lhs, const node& rhs) {
		return (lhs.x ^ rhs.x) ? (lhs.x < rhs.x) : (lhs.y < rhs.y);
	});
	for(int i = 1;i <= n;++ i) {
		int x = s[i].id;
		g[x] = query(s[i].y);
		stk[bel[x]].insert(x);
		int p = stk[bel[x]].query(x);
		f[x] = g[p] + 1ll * (x - p + 1) * (x - p + 1);
		add(s[i].y, f[x]);
	}
	i64 ans = 0;
	for(int i = 1;i <= n;++ i)
		chkmax(ans, f[i]);
	printf("%lld\n", ans);
	return 0;
}

标签:13,le,int,Ernd,long,UR,i64,maxn,id
From: https://www.cnblogs.com/663B/p/17553035.html

相关文章

  • ORA-03001: Unimplemented Feature
    一、创建主键添加online报错ORA-03001:unimplementedfeature二、官网解决办法ORA-03001:UnimplementedFeatureWhenAddingConstraintsWithOnlineClausefrom19.11(DocID2799005.1)1.19.16版本先添加唯一约束,在添加主键;2.在老版本可以使用online添......
  • 7.13日
    今天睡了个懒觉,十一点多才起,吃过午饭,简单洗漱陪姑姑和哥哥去剪头发和烫头,走出理发店已经快下午四点了,去钟楼合生汇的优衣库逛了一逛,哥哥买了四件衣服,我也看见一件较为喜欢的衣服,在网上下单了(身材高大,实体店一般都没有我的码),买完衣服在楼下探店了一家西餐,其它的都还好,牛排选错了,又......
  • 7月13日
    7月13日昨晚熬夜看小说导致今早九点多快十点才起床,然后发现我弟弟也没醒,把他叫起来然后洗漱,之后我妈让我帮忙打印一些文件,文件挺多的,关打印就打印了半个多小时,等到十一点左右就把我弟弟做的作业给检查了。然后我妈回来之后开始做饭,中间我小姨来串门,然后我就打了会儿游戏。吃完饭......
  • 2023.7.13 鲜花
    早晨:短暂地打了一会联考,然后看学弟打枪战&下棋。下午:好困好困,补觉补觉。晚上:下棋+学习国际象棋+围观别人下棋。真的是充实的一天!怎样才能不摆啊?怎样才能不摆啊?怎样才能不摆啊?怎样才能不摆啊?怎样才能不摆啊?怎样才能不摆啊?怎样才能不摆啊?......
  • 7.13
    昨天看着初一的小屁孩,太闹腾了,又是缺书,又是少啥的,全是问题,小屁孩的话还贼多,说了也不听,我tm真的服了,还跟着高一的铃声起床,精力充沛的一批,服了.让我提前四十分钟起床真的难受,还有就是,下午麻烦的一批,来回跑,然后晚上就跑了两万四千多步.累死我了.然后就是班里石刺头最多......
  • 7.13
    今天简单复习了一下前面学习东西继续学习了数组了解了数组的定义,数组的创建与声明,还有数组的越界问题空指针问题,就是因为引用类型变量没有指向任何对象,而访问了对象的属性或者是调用了对象的方法。读书然后睡觉了 明天计划上午学习吧,下午出门......
  • 2023.7.13拷逝
    T1原题链接看到最大值最小,考虑二分答案。接下来考虑如何构造\(b\)数组。因为\(b\)数组单调不减,所以当前的\(b\)越小,对后面的影响越小。所以构造时尽量小地构造\(b\),如果无法构造,说明当前的二分值不合法;如果构造成功,说明合法。\(code:\)#include<iostream>#include<cs......
  • LeetCode 剑指 Offer 13. 机器人的运动范围
    题目链接:LeetCode剑指Offer13.机器人的运动范围题意:地上有一个m行n列的方格,从坐标[0,0]到坐标[m-1,n-1]。一个机器人从坐标[0,0]的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机......
  • 7.13
    今天上午我大爷爷家的小孙子过满月,一大早就开车出去吃饭去了,下午去驾校练车,学了侧方停车和S型路和过直角弯,晚上的时候我爸一个朋友的儿子高考结束要我们两个同龄人认识一下,之后好帮帮忙啥的又出去吃饭了。今天没有打代码,就看了一会网课学习了方法的重写和super的讲解。......
  • 暑假训练2023.7.13
    CodeforcesRound884(Div.1+Div.2)A.SubtractionGame简单构造,输出a+bB.Permutations&Primes2和3都是质数,1不是,因此满足条件的区间一定包含1。把1放到序列最中间,2和3放到两端其他数字随意排列,可以证明此序列得到的素数mex的个数最大,为\(\lfloor\frac{n+1}{2}\rfl......