首页 > 其他分享 >CodeForces 1455G Forbidden Value

CodeForces 1455G Forbidden Value

时间:2022-10-04 08:11:31浏览次数:83  
标签:rt int Forbidden tree CodeForces Value SGT tag maxn

洛谷传送门

CF 传送门

小清新动态开点线段树优化 dp 题。

首先题目中的 if 嵌套看起来就很烦,可以考虑建树,外面再套一层大的 if 0 ... end,这样就将本题转化成一个树上问题。

考虑树形 dp。设 \(f_{u,i}\) 表示 从结点 \(u\) 出来时,\(x\) 的值是 \(i\) 的最少花费。

不难转移:

  • 对于 set 命令:

\(\begin{cases} f_{u,y} \gets \min\limits_{i}{f_{u,i}} \\ f_{u,i} \gets f_{u,i} + v & i \neq y \end{cases}\)

  • 对于 if 命令:

\(\begin{cases} f_{u,y} \gets f_{u,y} + f_{v,y} \\ f_{u,i} \gets \min(f_{u,i}, f_{u,y} + f_{v,i}) & i \neq y \end{cases}\)

注意转移时 dp 值都是同时计算。

直接暴力转移显然是 \(O(n^2)\) 的,但是我们发现对于每个结点 \(u\),真正有用的状态只有 \(u\) 子树内 \(y\) 的取值。可以考虑对每个结点开一个动态开点线段树,存 \(u\) 的所有状态。转移时只需单点修改、整体加和单点查询,对于 if 命令大力线段树合并即可。时间复杂度 \(O(n \log n)\)。

map + 启发式合并的做法看不懂,我太菜了。

code
/*

p_b_p_b txdy
AThousandSuns txdy
Wu_Ren txdy
Appleblue17 txdy

*/

#include <bits/stdc++.h>
#define pb push_back
#define fst first
#define scd second
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 200100;
const int N = 200000;
const ll inf = 0x3f3f3f3f3f3f3f3fLL;

int rt[maxn], n, m, stk[maxn], top, tot;
// int head[maxn], len;
vector<int> G[maxn];

struct node {
	int x, v, op;
	node(int a = 0, int b = 0, int c = 0) : x(a), v(b), op(c) {}
} a[maxn];

// struct edge {
	// int to, next;
// } edges[maxn];
// 
// void add_edge(int u, int v) {
	// edges[++len].to = v;
	// edges[len].next = head[u];
	// head[u] = len;
// }

namespace SGT {
	ll tree[maxn * 30], tag[maxn * 30];
	int ntot, ls[maxn * 30], rs[maxn * 30];
	
	void clear() {
		ntot = 0;
		mems(tree, 0x3f);
		mems(tag, 0);
		mems(ls, 0);
		mems(rs, 0);
	}
	
	void pushup(int x) {
		tree[x] = min(tree[ls[x]], tree[rs[x]]);
	}
	
	void pushdown(int x) {
		if (!tag[x]) {
			return;
		}
		if (ls[x]) {
			tree[ls[x]] += tag[x];
			tag[ls[x]] += tag[x];
		}
		if (rs[x]) {
			tree[rs[x]] += tag[x];
			tag[rs[x]] += tag[x];
		}
		tag[x] = 0;
	}
	
	void updpos(int &rt, int l, int r, int x, ll y) {
		if (!rt) {
			rt = ++ntot;
		}
		// printf("upd: %d %d %d %d %lld\n", rt, l, r, x, y);
		if (l == r) {
			tree[rt] = y;
			return;
		}
		pushdown(rt);
		int mid = (l + r) >> 1;
		if (x <= mid) {
			updpos(ls[rt], l, mid, x, y);
		} else {
			updpos(rs[rt], mid + 1, r, x, y);
		}
		pushup(rt);
	}
	
	void update(int rt, ll x) {
		tree[rt] += x;
		tag[rt] += x;
	}
	
	ll query(int rt, int l, int r, int x) {
		// printf("%d %d %d %d\n", rt, l, r, x);
		if (!rt) {
			return inf;
		}
		if (l == r) {
			return tree[rt];
		}
		pushdown(rt);
		int mid = (l + r) >> 1;
		if (x <= mid) {
			return query(ls[rt], l, mid, x);
		} else {
			return query(rs[rt], mid + 1, r, x);
		}
	}
	
	int merge(int u, int v, int l, int r) {
		if (!u || !v) {
			return u | v;
		}
		if (l == r) {
			tree[u] = min(tree[u], tree[v]);
			return u;
		}
		pushdown(u);
		pushdown(v);
		int mid = (l + r) >> 1;
		ls[u] = merge(ls[u], ls[v], l, mid);
		rs[u] = merge(rs[u], rs[v], mid + 1, r);
		pushup(u);
		return u;
	}
}

void dfs(int u) {
	SGT::updpos(rt[u], 0, N, a[u].x, 0);
	for (int v : G[u]) {
		if (a[v].op == 1) {
			ll tmp = SGT::tree[rt[u]];
			SGT::update(rt[u], a[v].v);
			if (a[v].x != m) {
				SGT::updpos(rt[u], 0, N, a[v].x, tmp);
			}
		} else {
			ll tmp = SGT::query(rt[u], 0, N, a[v].x);
			if (tmp < inf) {
				dfs(v);
				SGT::update(rt[v], tmp);
				SGT::updpos(rt[u], 0, N, a[v].x, inf);
				rt[u] = SGT::merge(rt[u], rt[v], 0, N);
			}
		}
	}
}

void solve() {
	SGT::clear();
	scanf("%d%d", &n, &m);
	stk[++top] = 0;
	for (int i = 0; i < n; ++i) {
		char op[9];
		scanf("%s", op);
		if (op[0] == 's') {
			int x, y;
			scanf("%d%d", &x, &y);
			a[++tot] = node(x, y, 1);
			G[stk[top]].pb(tot);
		} else if (op[0] == 'i') {
			int x;
			scanf("%d", &x);
			a[++tot] = node(x, 0, 2);
			G[stk[top]].pb(tot);
			stk[++top] = tot;
		} else {
			--top;
		}
	}
	dfs(0);
	printf("%lld\n", SGT::tree[rt[0]]);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:rt,int,Forbidden,tree,CodeForces,Value,SGT,tag,maxn
From: https://www.cnblogs.com/zltzlt-blog/p/16753130.html

相关文章

  • Codeforces Round #823 (Div. 2) A-D
    比赛链接A题解知识点:贪心。对于一个轨道,要么一次性清理,要么一个一个清理。显然,如果行星个数大于直接清理的花费,那么选择直接清理,否则一个一个清理。即\(\sum\min(c,......
  • [Typescript] Tips: Use 'extends' keyword to narrow the value of a generic
    exportconstgetDeepValue=<Obj,FirstKeyextendskeyofObj,SecondKeyextendskeyofObj[FirstKey]>(obj:Obj,firstKey:FirstKey,secondKey:SecondKey......
  • codeforces/AtCoder补题整理
    目录cf1738CEvenNumberAddicts(博弈/记忆化搜索)题意题解cf1739EResetKEdges(树,二分+贪心)题意题解cf1730DPrefixesandSuffixes(字符串,思维)题意题解cf1734DS......
  • Codeforces Global Round 22 C. Even Number Addicts(博弈论)
    https://codeforces.com/contest/1738/problem/C题目大意:给定n个数字,Alice先手,Bob后手;拿完之后,Alice数字总和为奇数时Alice获胜,否则Bob获胜。问我们给定n个数字,双方......
  • Dashboard - Codeforces Round #824 (Div. 2) - Codeforces
    Dashboard-CodeforcesRound#824(Div.2)-Codeforces1.Problem-A-Codeforces考虑第一部分只取一天然后第二部分取1/3,最后一天取剩下的。然后再中间的增大,第三......
  • Springboot 之 HandlerMethodReturnValueHandler 运用
    简介现在项目中大部分采用前后端分离的架构,采用这种架构的项目,在返回数据时,几乎都是采用返回json格式的数据。而spring中返回json格式的数据一般采用@RestControll......
  • Codeforces Global Round 22 C
    C.EvenNumberAddicts本人没学过博弈论在https://zhuanlan.zhihu.com/p/569862415的指导下写一些自己的理解首先我们可以想到的就是搜索!最坏情况下应该是2^50次方......
  • Codeforces Global Round 22 D
    D.PermutationAddicts我们观察给的条件发现不是那么明朗我们把x变成ai看看ifa[i]<=kb[a[i]]:=a[j](j<i)&&a[j]>k如果没有就把b[a[i]]:=n+1肯定还是>k的这......
  • Spring源码-applyPropertyValues
    applyPropertyValuesprotectedvoidapplyPropertyValues(StringbeanName,BeanDefinitionmbd,BeanWrapperbw,PropertyValuespvs){ if(pvs.isEmpty()){ ret......
  • Codeforces Global Round 22
    CodeforcesGlobalRound22A#include<iostream>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#defineendl'\n'usingnamespacestd;co......