zoukankan      html  css  js  c++  java
  • Codeforces 1320C World of Darkraft: Battle for Azathoth

    Description

    给定一系列有代价的装备,第一种提供 $x$ 值,第二种提供 $y$ 值。给出一些怪兽,如果怪兽的 $x_i$​ 和 $y_i$​ 都小于选定的 $x$ 和 $y$ ,那么会有 $z_i$​ 的奖励。最大化收益。

    Solution

    Algorithm 1

    枚举武器 $i$,防具 $j$,再遍历每一个怪物,算出总奖励 $sumlimits_{x<a_i, y<b_j} z$,记为 $sum$,用 $sum - ca_i - cb_j$ 去更新答案。

    时间复杂度 $mathcal O(nmp)$。

    Algorithm 2

    能不能弄点单调性出来呢?

    我们将武器按照 $a$ 排序,怪物按照 $x$ 排序。

    这时候,如果我们从小到大枚举武器,而且 只考虑 $x$ 部分的话,能打的怪物也是一个 前缀

    但是只有武器是不行的,还要防具,但要是再枚举不又回到了 Algorithm 1 了吗?这个单调性似乎一点都没用啊?

    正难则反,既然没法已知 $b$ 去枚举怪物,我们索性按照 $x$ 属性依次添加怪物,用 $val_b$ 来表示当防具的威力为 $b$ 时,最高的奖励。

    如果某一个 $b$ 值的防具都没出现,那么 $val_b$ 自然是 $-infty$,否则,$val_b$ 的 初始值应当是 $-cb_b$,表示一次购买。

    那么,对于一个怪物,根据前缀性质,我们可以类似 two-pointers 的加入,怪物的 $x$ 属性自然是满足条件的了,这时将 $[y+1, infty]$ 的 $val_b$ 加上 $z$,表示配合一个威力值至少为 $y+1$ 的防具,就可以肝掉这个怪兽了。

    $max{val}$ 就是最优方案,当然 $a$ 的代价是没有考虑进去的,所以用 $max{val}-ca_i$ 更新答案。

    实际上,因为 $b le 10^6$,所以修改/查询都进行到 $10^6$ 即可。

    时间复杂度 $mathcal O(n ext{ max}{b})$。$p$ 和 $n$ 不区分。

    Algorithm 3

    进一步分析两个操作。

    你干了啥?区间(后缀)加,整体 $max$。

    一个线段树直接搞定!

    所以用线段树维护 $val$ 数组即可。

    时间复杂度 $mathcal{O(n log ext{max}{b})}$。

    下面是 AC 代码。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 1e6 + 5;
    struct weapon
    {
    	LL a, ca;
    	bool operator < (const weapon &oth) const { return a < oth.a; }
    } wea[N];
    struct monster
    {
    	LL x, y, z;
    	bool operator < (const monster &oth) const { return x < oth.x; }
    } mon[N];
    LL n, m, p, val[N], ans = LLONG_MIN; // ans 一定要赋极小值! 
    struct segment_tree // 线段树相关 
    {
    #define ROOT 1, N - 5, 1
    #define LSON l, mid, rt << 1
    #define RSON mid + 1, r, rt << 1 | 1
    	struct node
    	{
    		LL maxx, col;
    	} o[N << 2];
    	inline void update(int rt)
    	{
    		o[rt].maxx = max(o[rt << 1].maxx, o[rt << 1 | 1].maxx);
    	}
    	void build(int l, int r, int rt)
    	{
    		o[rt].col = 0;
    		if(l == r)
    		{
    			o[rt].maxx = val[l];
    			return;
    		}
    		int mid = l + r >> 1;
    		build(LSON); build(RSON);
    		update(rt);
    	}
    	inline void color(int rt, LL v)
    	{
    		o[rt].col += v;
    		o[rt].maxx += v;
    	}
    	inline void pushcol(int rt)
    	{
    		if(!o[rt].col) return;
    		color(rt << 1, o[rt].col);
    		color(rt << 1 | 1, o[rt].col);
    		o[rt].col = 0;
    	}
    	void modify(int l, int r, int rt, int ml, int mr, LL v)
    	{
    		if(ml <= l && r <= mr) 
    		{
    			color(rt, v);
    			return;
    		}
    		int mid = l + r >> 1;
    		pushcol(rt);
    		if(ml <= mid) modify(LSON, ml, mr, v);
    		if(mr > mid) modify(RSON, ml, mr, v);
    		update(rt);
    	}
    } sgt;
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin >> n >> m >> p;
    	for(register int i = 1; i < N; i++) val[i] = LLONG_MIN;
    	for(register int i = 1; i <= n; i++) cin >> wea[i].a >> wea[i].ca;
    	for(register int i = 1; i <= m; i++)
    	{
    		LL b, cb;
    		cin >> b >> cb;
    		val[b] = max(val[b], -cb); // 更新线段树初始叶子节点权值 
    	}
    	sgt.build(ROOT);
    	sort(wea + 1, wea + n + 1);
    	for(register int i = 1; i <= p; i++) cin >> mon[i].x >> mon[i].y >> mon[i].z;
    	sort(mon + 1, mon + p + 1);
    	int cur = 1;
    	for(register int i = 1; i <= n; i++)
    	{
    		while(cur <= p && wea[i].a > mon[cur].x) // 类似 two-pointers 计算贡献 
    		{
    			if(mon[cur].y != N - 5)
    				sgt.modify(ROOT, mon[cur].y + 1, N - 5, mon[cur].z);
    			cur++;
    		}
    		ans = max(ans, sgt.o[1].maxx - wea[i].ca); // 全局 max,也就是根节点 
    	}
    	cout << ans << endl;
    	return 0;
    }

    Algorithm 4

    什么?$10^6$ 带 $log$ 不稳?

    离散化解决一切!

    时间复杂度 $mathcal O(nlog m)$。本质上就是去掉了 $val = -infty$ 的情况。

    当然,这个优化是完全不必要的。

  • 相关阅读:
    1046 Shortest Distance (20 分)(模拟)
    1004. Counting Leaves (30)PAT甲级真题(bfs,dfs,树的遍历,层序遍历)
    1041 Be Unique (20 分)(hash散列)
    1036 Boys vs Girls (25 分)(查找元素)
    1035 Password (20 分)(字符串处理)
    1044 Shopping in Mars (25 分)(二分查找)
    onenote使用小Tip总结^_^(不断更新中...)
    1048 Find Coins (25 分)(hash)
    三个故事
    领导者的举止
  • 原文地址:https://www.cnblogs.com/syksykCCC/p/CF1320C.html
Copyright © 2011-2022 走看看