首页 > 其他分享 >【UOJ 710】魔塔 OL(贪心)(四毛子分块)

【UOJ 710】魔塔 OL(贪心)(四毛子分块)

时间:2022-10-21 09:00:07浏览次数:169  
标签:OL 分块 int 魔塔 然后 710 毛子 include 贪心

魔塔 OL

题目链接:UOJ 710

题目大意

有一个三维的网格,点有权值 a,b,维护三个操作:
加入一个点,删除一个点, 把某一个 (1,x)(1,y)(1,y) 立方体里面的点拿出来,做一次操作的最小初始值。
操作是你按某个顺序删点,先把你的值减 a,再加上 b,要保证你的数不会小于 0 的最小初始值。

思路

首先考虑给出点集怎么做。
那你不难得到一个贪心:
首先选会让总值增加的 \(a\leqslant b\),那这其中我们肯定是要求从低到高,所以这些按 \(a\) 从小到大排。
那接着是 \(a>b\),那减的总数已经确定,那我们肯定是尽可能的维持数大(在过程中),那你选某个数的时候,它的 \(a\) 是必减的,所以我们可以按 \(b\) 从大到小排。

那然后贪心看就行,接着看怎么快一点。
我们把所有点重新按这个贪心排序,然后我们考虑四毛子分块。


四毛子分块的想法是,我们选取一个很小的块,然后块内暴力处理出每一种情况的答案,然后跟之前的联系起来。


这里的话,我们就是 \(2^B\) 算出里面每个点在或者不在,对块内做贪心的结果(要记录最后的和以及答案)
然后我们在求出每一维你 \(1\sim x\) 包含了那些点,那三维的话就是三个点集的交。

但是会有一个小问题没有处理,就是它每个点有一个出现的区间(会删去)
那这个你拿左右两个指针扫,维护这个区间中的点集,然后再跟前面的取并即可。
然后就合并入之前的答案。

\(B\) 大概取 \(\log\) 的位置,用 \(14\)。

然后每次的时间就是 \(O(\dfrac{n^2+nq}{\log n})\)

代码

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define ll long long

using namespace std;

const int N = 5e4 + 100;
const int V = 1e4 + 100;
const int B = 14;
struct Monster {
	int l, r, x, y, z;
	int a, b;
}a[N];
struct Quest {
	int x, y, z, tim;
}qs[N];
int n, tot, q, lsts[1 << B], tim;
int xs[N], ys[N], zs[N];
ll sum[1 << B], maxn[1 << B], sums[N], ans[N];
vector <pair <int, int> > Ls, Rs;

bool cmp(Monster x, Monster y) {
	if ((x.a <= x.b) ^ (y.a <= y.b)) return x.a <= x.b;
	if (x.a <= x.b) return x.a < y.a;
		else return x.b > y.b;
}

void work(int l, int r) {
	int len = r - l + 1;
	memset(xs, 0, sizeof(xs)); memset(ys, 0, sizeof(ys)); memset(zs, 0, sizeof(zs));
	for (int i = l; i <= r; i++) {
		xs[a[i].x] |= (1 << (i - l));
		ys[a[i].y] |= (1 << (i - l));
		zs[a[i].z] |= (1 << (i - l));
	}
	for (int i = 1; i < N; i++) xs[i] |= xs[i - 1], ys[i] |= ys[i - 1], zs[i] |= zs[i - 1];
	for (int i = 1; i < (1 << len); i++) {
		int id = lsts[i], fr = i ^ (1 << id); id += l;
		maxn[i] = max(maxn[fr], sum[fr] + a[id].a);
		sum[i] = sum[fr] + a[id].a - a[id].b;
	}
	Ls.clear(); Rs.clear();
	for (int i = l; i <= r; i++) Ls.push_back(make_pair(a[i].l, i - l)), Rs.push_back(make_pair(a[i].r, i - l));
	sort(Ls.begin(), Ls.end()); sort(Rs.begin(), Rs.end());
	int lnum = 0, rnum = 0, suml = 0, sumr = 0;
	for (int i = 1; i <= q; i++) {
		while (lnum < len && Ls[lnum].first <= qs[i].tim) {
			suml |= (1 << Ls[lnum].second); lnum++;
		}
		while (rnum < len && Rs[rnum].first <= qs[i].tim) {
			sumr |= (1 << Rs[rnum].second); rnum++;
		}
		int S = xs[qs[i].x] & ys[qs[i].y] & zs[qs[i].z] & (suml ^ sumr);
		ans[i] = max(ans[i], sums[i] + maxn[S]);
		sums[i] += sum[S];
	}
}

int main() {
	for (int i = 1; i < (1 << B); i++) {
		for (int j = 0; j < B; j++)
			if ((i >> j) & 1) lsts[i] = j;
	}
	
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		char op = getchar(); while (op != '+' && op != '-' && op != '?') op = getchar();
		if (op == '+') {
			int x, y, z, A, b; scanf("%d %d %d %d %d", &x, &y, &z, &A, &b);
			a[++tot] = (Monster){++tim, n, x, y, z, A, b};
		}
		if (op == '-') {
			int k; scanf("%d", &k);
			a[k].r = ++tim;
		}
		if (op == '?') {
			int x, y, z; scanf("%d %d %d", &x, &y, &z);
			qs[++q] = (Quest){x, y, z, tim};
		}
	}
	
	sort(a + 1, a + tot + 1, cmp);
	for (int i = 1; i <= tot; i += B) {
		int j = min(tot, i + B - 1);
		work(i, j);
	}
	
	for (int i = 1; i <= q; i++) printf("%lld\n", ans[i]);
	
	return 0;
}

标签:OL,分块,int,魔塔,然后,710,毛子,include,贪心
From: https://www.cnblogs.com/Sakura-TJH/p/UOJ_710.html

相关文章

  • drools_06_stateless_vs_stateful
    06_stateless_vs_statefulstatelesssession适用场景:适合一次启动规则引擎完成全量fact的计算,它不支持增量计算.execution()方法通常传入一个对象清单,要计算的......
  • Golang基础-变量与数据类型
    变量变量的定义1.声明2.赋值3.使用//声明:var变量名变量类型varnamestring//赋值:name="xiaoming"//使用:fmt.Println(name)//声明+赋值//var变......
  • java----Collection集合
    Collection集合1、集合与数组的相同点是什么?  都是容器,可以存储多个数据2、集合与数组的不同点是什么?  ①.数组的长度是不可变的,集合的长度是可变的  ②.......
  • TabControl控件
    TabControl控件,页面集合用于管理一个TabPages集合,每个TabPage都是一个容器控件 常用属性:MultiLine,TabPages,AlignMent,Appearance,ItemSize,ImagesList  知识点1:Mu......
  • golang中的切片
    索引:https://waterflow.link/articles/1666277946416在go中切片的底层是数组,所以切片的数据连续存储在数组的数据结构中。如果底层的数组满了,切片还需要添加元素的话,底层数......
  • golang中的切片
    索引:https://waterflow.link/articles/1666277946416在go中切片的底层是数组,所以切片的数据连续存储在数组的数据结构中。如果底层的数组满了,切片还需要添加元素的话,底层......
  • Go 语言入门很简单:什么是 Golang
    Golang是一种相对较新的编程语言,很快就流行起来。StackOverflow对开发人员进行了民意调查,发现Golang是学习Go编程语言的第三大热门。为了更好地理解为什么Go如此......
  • Prometheus 运维工具 Promtool (四)TSDB 功能
    Promtool在TSDB方面一个有6个子命令,分别用来进行写性能测试、分析、列出其中的块、dump、从OpenMetric导入数据块、为新的记录规则创建数据块,接下来我们依次看一下。......
  • 群晖(Synology)NAS 安装 MongoDB
    首先需要在群晖的Docker中选择Image,然后选择添加。  输入DockerHUB的地址在弹出的对话框中输入DockerHub的地址。MongoDB的地址为: DockerHub  ......
  • (九)MySQL基础知识之 事务(commit, rollback,begin,set autocommit)
    昨天说了下MySQL的正则表达式,今天我们来说下事务的基础知识。 什么是MySQL的事务呢? 事务是由一步或几步数据库操作序列组成逻辑执行单元,这一系列操作要么全部执行,要么全......