首页 > 其他分享 >CF1455G Forbidden Value 题解

CF1455G Forbidden Value 题解

时间:2022-08-29 16:23:19浏览次数:99  
标签:... end int 题解 Forbidden Value tag ll minv

CF1455G Forbidden Value

已知初始值\(x=0\),给定下面2种命令:

  1. set \(y\) \(v\),令\(x=y\),或花费\(v\)元钱删除该命令;
  2. if \(y\) ... end,如果\(x==y\),执行if...end中的命令,否则跳过该if...end

你需要使用最少的花费,使得无论运行到哪里,都有\(x \neq s\)。

可以考虑对这些命令建树,对于每个 if...end 这个命令中的命令,其父亲节点为这个 if。整个程序可以看作在一个 if 0 ... end 命令中,这个命令为根节点。这个建树用一个栈就可以实现了。

然后我们考虑一个比较显然的动态规划。定义 \(dp_{i,j}\) 表示执行子树 \(i\) 中的命令,最后的数为 \(j\) 的最小花费。如果现在有 set y v 操作,将所有下标非 \(y\) 的 \(dp\) 值变大 \(v\),\(y\) 位置的值不变(注意判断是否\(y=s\))。对于 if y ...end 操作,可以计算出这个 if 子树内的 \(dp\) 数组,然后对于 \(y\) 位置,更改为子树内的 \(dp\) 值,对于非 \(y\) 位置,原数组与子树数组取最小值即可。

这个 \(dp\) 可以使用线段树合并优化。就是上述过程用线段树合并实现。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
typedef long long ll;
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*f;
}
const int N=200005,M=200000;
ll INF=0x3f3f3f3f3f3f3f3f;
int n,s;
struct options{int op,y;ll v;}opt[N];
vector<int>edge[N];
int lc[N*20],rc[N*20],rt[N],tot;ll minv[N*20],tag[N*20];
#define mid ((l+r)>>1)
inline void modify(int p,ll v){minv[p]+=v;tag[p]+=v;}
inline void pushup(int p){minv[p]=min(minv[lc[p]],minv[rc[p]]);}
inline void pushdown(int p){
	if(!tag[p])return;
	if(lc[p])modify(lc[p],tag[p]);
	if(rc[p])modify(rc[p],tag[p]);
	tag[p]=0;
}
void change(int &p,int l,int r,int L,ll v){
	if(!p)minv[p=++tot]=INF;
	if(l==r){minv[p]=v;return;}
	pushdown(p);
	if(L<=mid)change(lc[p],l,mid,L,v);
	else change(rc[p],mid+1,r,L,v);
	pushup(p);
}
ll query(int p,int l,int r,int L){
	if(!p)return INF;
	if(l==r)return minv[p];
	pushdown(p);
	if(L<=mid)return query(lc[p],l,mid,L);
	return query(rc[p],mid+1,r,L);
}
int merge(int x,int y,int l,int r){
	if(!x||!y)return x+y;
	if(l==r){minv[x]=min(minv[x],minv[y]);return x;}
	pushdown(x);pushdown(y);
	lc[x]=merge(lc[x],lc[y],l,mid);
	rc[x]=merge(rc[x],rc[y],mid+1,r);
	pushup(x);return x;
}
void dfsp(int u){
	change(rt[u],0,M,opt[u].y,0);
	for(auto v:edge[u]){
		if(opt[v].op==1){
			ll tmp=minv[rt[u]];
			modify(rt[u],opt[v].v);
			if(opt[v].y!=s)change(rt[u],0,M,opt[v].y,tmp);
		}else{
			ll tmp=query(rt[u],0,M,opt[v].y);
			if(tmp!=INF){
				dfsp(v);
				modify(rt[v],tmp);
				change(rt[u],0,M,opt[v].y,INF);//如果我们能进入这个 If 语句,那么显然 dp_{u,y} 的代价要重新计算,必须删除原有贡献
				rt[u]=merge(rt[u],rt[v],0,M);//不然这里 dp_{u,y} 还会保留原先的值。
			}
		}
	}
}
int stk[N],top=0;
int main(){
	scanf("%d%d",&n,&s);int nod=1;
	stk[++top]=nod;
	char s[10];
	for(int i=1;i<=n;++i){
		scanf("%s",s);
		if(s[0]=='s'){
			opt[++nod].op=1;
			opt[nod].y=read(),opt[nod].v=read();
			edge[stk[top]].push_back(nod);
		}else if(s[0]=='i'){
			opt[++nod].op=2;
			opt[nod].y=read();
			edge[stk[top]].push_back(nod);
			stk[++top]=nod;
		}else --top;
	}
	minv[0]=INF;dfsp(1);
	printf("%lld\n",minv[rt[1]]);
	return 0;
}

标签:...,end,int,题解,Forbidden,Value,tag,ll,minv
From: https://www.cnblogs.com/BigSmall-En/p/16636342.html

相关文章

  • Map遍历 key-value 的4种方法
    四种方法先用keySet()取出所有key值,再取出对应value——增强for循环遍历先用keySet()取出所有key值,再取出对应value——使用迭代器遍历通过entrySet来获取key-value—......
  • 题解 树套树
    题面二叉查找树(BST)是一种简单的数据结构,本题默认你已经熟悉BST的插入和查询两种操作。给你一棵树,每个节点有一个BST。有以下两种操作:\(u,v,k\):在路径\((u,v)\)上每......
  • AtCoder Beginner Contest 266 题解
    只有ABCDEFG的题解。A模拟。代码voidmian(){strings;cin>>s;intpos=int(s.size())/2;cout<<s[pos]<<endl;}B模拟,注意longlong。......
  • pip下载慢问题解决方案
    在使用Python开发过程中,经常要用pip安装软件包,但是直接使用pipinstallpackagename经常慢得要死,而且慢就算了很多时候还下载完成安装失败。问题原因pip默认使用的是国外......
  • P1003 [NOIP2011 提高组] 铺地毯 题解
    题目传送门[NOIP2011提高组]铺地毯题目描述为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有\(n\)......
  • Python 报错:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char
    报错内容:json.decoder.JSONDecodeError:Expectingvalue:line1column1(char0) 报错代码:print(res.json()) 报错原因:打印请求返回值报错该接口返回值......
  • MQ的消息丢失/重复/积压的问题解决
    在我们实际的开发过程中,我们肯定会用到MQ中间件,常见的MQ中间件有kafka,RabbitMQ,RocketMQ。在使用的过程中,我们必须要考虑这样一个问题,在使用MQ的时候,我们怎么确保消息100%......
  • CF123E Maze 题解
    提供一种不太一样的换根dp的做法。记\(u\)作为起点的概率为\(q_u\),作为终点的概率为\(p_u\)。题目给的代码可以看作一个从某个点开始,以它为根dfs到终点的步数,这......
  • P1002 [NOIP2002 普及组] 过河卒 题解
    题目:[NOIP2002普及组]过河卒题目描述棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点。卒行走的规则:可以向下、或者向右。同时在棋盘上\(C\)点有一个对方的马,该......
  • 洛谷 P8496 [NOI2022] 众数 题解
    最近7年最水的D1T1。用权值线段树维护每个数出现的次数,链表维护序列。操作4即合并两棵权值线段树、两个链表,操作2就是删除链表尾的元素并在权值线段树上修改。显......