首页 > 其他分享 >Rainbow Bracket Sequence

Rainbow Bracket Sequence

时间:2024-09-18 22:25:12浏览次数:10  
标签:Rainbow cnt 颜色 Sequence int ll len 括号 Bracket

The 2024 ICPC Asia East Continent Online Contest (I)

题意

构造长度为 \(2n\) 的合法括号序列。

对于每个左括号在的位置 \(i\), 都有颜色 \(c_i\) 和价值 \(v_i\)。

左括号颜色视为所在位置颜色, 价值同理。

对于每个颜色,满足左括号为该颜色的个数 \(\geq l_i\)。

求满足以上条件下,最大左括号的价值和。

\(n \leq 100, m \leq n, v_i \leq 10^9\)。

做法

是费用流,关键在于建模。

  • 保证合法括号序列

首先构建点 \(1 \dots 2n\) 表示所有括号序列。

把原点 \(S\) 连向所有奇数点,即 \(S \to 1, S\to 3, \dots, S \to 2n - 1\)。

流量,边权 为 \((1, 0)\), 即表示左括号在这些点。

同时,对 \(i + 1 \to i\), 连 \((+\infty, 0)\), 表示左括号可以向左移动。

可以发现, 这样构造出来的括号序列总是合法的, 总能保证左右括号匹配且任意前缀左括号个数大于等于右括号个数。

  • 颜色限制

首先, 每个位置 \(i\) 连向对应颜色 \(c_i\), 边权为 \(-v_i\), 流量为 \(1\)。

为了保证颜色 \(i\) 有 \(l_i\) 个, 连 \(c_i \to T\) 时, 流量为 \(l_i\), 边权为 \(-\infty\),(可以是极小的数 \(-10^{13}\)) 表示一定要选。

对于超过 \(l_i\) 的部分,连 \(c_i \to T\) 的 \((\infty, 0)\) 的边, 表示可以选。

  • 跑最小费用最大流即可

求得 \(\lfloor\frac{\text{mincost}}{-10^{13}}\rfloor = \sum l_i\), 即有解,

最后的答案为 \(\text{mincost} \mod (-10^{13})\)。

code

#include<bits/stdc++.h>
using namespace std;
using ll = long long;  
const int N = 10100;
const ll INF = 1e13; 

int n, m, s, t;
int col[N], val[N], l[N]; 

struct edge {
	int v, len, next;
	ll w;  
} e[N];
int cnt;
int first[N], cur[N]; 

void add(int u, int v, int len, ll w) {
	++ cnt;
	e[cnt].v = v;
	e[cnt].len = len; 
	e[cnt].w = w; 
	e[cnt].next = first[u];
	first[u] = cnt; 
}
void Add(int u, int v, int len, ll w) {
	add(u, v, len, w); 
	add(v, u, 0, -w); 
} 
void init() {
	cnt = 1; 
	s = 2 * n + m + 1, t = 2 * n + m + 2; 
	for (int i = 1; i <= t; i ++)
		first[i] = 0;   
}

bool vis[N];
ll dis[N];  
bool bfs() {
	memcpy(cur, first, sizeof(first)); 
	for (int i = 1; i <= t; i ++)
		vis[i] = 0, dis[i] = INF;
	queue<int> q; 
	q.push(s); 
	dis[s] = 0; 
	while (!q.empty()) {
		int u = q.front(); q.pop();
		vis[u] = 0; 
		for (int i = first[u]; i; i = e[i].next) {
			int v = e[i].v, len = e[i].len;
			ll w = e[i].w; 
			if (!len || dis[v] <= dis[u] + w) continue;
			dis[v] = dis[u] + w;
			if (!vis[v]) {
				q.push(v),
				vis[v] = 1; 
			}
		}
	}
	return dis[t] != INF; 
}
ll cost; 
int dfs(int u, int flow) {
	if (u == t) {
		return flow; 
	}
	int ans = 0; 
	vis[u] = 1;
	for (int &i = cur[u]; i; i = e[i].next) {
		int v = e[i].v, len = e[i].len; ll w = e[i].w; 
		if (vis[v] || dis[v] != dis[u] + w || !len) continue; 
		int out = dfs(v, min(len, flow));
		if (out) {
			ans += out; 
			cost += 1ll * out * w; 
			e[i].len -= out;
			e[i ^ 1].len += out; 
			flow -= out; 
		} 
	}
	return ans; 
}
ll dinic() {
	ll ans = 0; 
	while (bfs()) {
		cost = 0; 
		dfs(s, 0x7fffffff);
		ans += cost;
	}
	return ans; 
}

void solve() {
	cin >> n >> m; 
	init(); 
	int suml = 0; 
	for (int i = 1; i <= m; i ++)
		cin >> l[i], suml += l[i];
	for (int i = 1; i <= 2 * n; i ++)	
		cin >> col[i]; 
	for (int i = 1; i <= 2 * n; i ++)
		cin >> val[i]; 
		
	for (int i = 1; i <= 2 * n; i += 2)
		Add(s, i, 1, 0); 
	for (int i = 1; i <= 2 * n - 1; i ++) 
		Add(i + 1, i, 0x7fffffff, 0); 
	for (int i = 1; i <= 2 * n; i ++)
		Add(i, 2 * n + col[i], 1, - val[i]); 
	for (int i = 1; i <= m; i ++) {
		Add(2 * n + i, t, l[i], -INF);
		Add(2 * n + i, t, 0x7fffffff, 0); 
	}
	ll cost = dinic();
	if (cost / (-INF) == suml) {
		cout << (-cost) % INF << endl;
	} else
		cout << -1 << endl;
} 

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0); 
	int T;
	cin >>T;
	while (T --)
		solve(); 
	return 0;
}

最后 %%%klii , 感谢他的图和教导。

标签:Rainbow,cnt,颜色,Sequence,int,ll,len,括号,Bracket
From: https://www.cnblogs.com/qjbqjb/p/18419473

相关文章

  • Rainbow Bracket Sequence
    括号序列匹配+最优化问题+一系列限制条件+较小的数据范围=最小费用最大流模型拆点难以解决重复的问题,既然如此那就不拆点了,用流向代表左右括号的选择每一次bfs,总流量增加,总费用也是增加的,但是退流的边还是要归还费用【直觉就不对劲呀,多想一下吧】注意,当li的限制超过节点总数时......
  • CF1144G Two Merged Sequences
    首先我们考虑最暴力的方法,仿照着LIS板子题设计状态:\(dp_{i,j}\)表示考虑前\(\max(i,j)\)个,单减序列以\(i\)结尾,单增序列以\(j\)结尾,然后进行\(O(1)\)的转移。但是这样状态数就爆炸了,如何优化状态数呢?我们考虑进行换维。因为我们刚刚设计的是一个弱鸡的可行性DP,很强......
  • Java零基础-replace(CharSequence target, CharSequence replacement)详解
    哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者......
  • [AGC003E] Sequential operations on Sequence
    题意给定一个整数序列,有\(q\)次操作,每次操作从无限复制的序列里面选择前\(q_i\)个元素作为当前的序列。问\(1\)到\(n\)每个整数在最终序列中出现的次数。\(n\le10^5,q_i\le10^{18}\)Sol想象一下每次操作,都是复制若干次前一次的序列然后拼上一段余数组成的。......
  • 【P4552】IncDec Sequence
    因为前缀和/差分学习的时候就不熟,所以特选本题作为训练作为一道差分题,本题的思路也是特别的绕,首先进行基础知识的复习【差分】简单来说就是两个数的差,b[i]=a[i]-a[i-1]把序列a的区间[l,r]+d的话,差分序列b则进行以下变化:   b[l]+d,b[r+1]-d前置知识大概就这些,下面进行题......
  • CF1621G Weighted Increasing Subsequences 题解
    题目链接点击打开链接题目解法这种题就感觉每一步都不难想,但串在一起就不会显然考虑位置\(x\)作为\(lis\)的一部分,合法的\(lis\)的个数合法的约束是:令\(lis\)的最后一个位置为\(last\),满足\(\max\{a_{last+1},...,a_n\}>a_x\)不难发现,合法的\(last\)是一段区间......
  • 浙大数据结构:02-线性结构4 Pop Sequence
    这道题我们采用数组来模拟堆栈和队列。简单说一下大致思路,我们用栈来存1234.....,队列来存输入的一组数据,栈与队列进行匹配,相同就pop1、条件准备stk是栈,que是队列。tt指向的是栈中下标,front指向队头,rear指向队尾。初始化栈顶为0,队头为0,队尾为-1#include<iostream>usingn......
  • [ABC221G] Jumping sequence
    MyBlogs[ABC221G]Jumpingsequence做法有点深刻,优化方式非常深刻。首先是哈密顿距离和切比雪夫距离的转化:把坐标系旋转四十五度,变成每次向左上,右上,左下,右下走\(\sqrt2a_i\)的距离,要求最后走到\((A+B,A-B)\)。然后这样可以对于横纵坐标分开做了(非常神奇)。问题转化成了询......
  • 浙大数据结构:01-复杂度2 Maximum Subsequence Sum
    数据结构MOOCPTA习题01-复杂度2MaximumSubsequenceSum#include<iostream>usingnamespacestd;constintM=100005;inta[M];intmain(){ intk; cin>>k; intf=1; for(inti=0;i<k;i++) { cin>>a[i]; if(a[i]>=0)//如......
  • CF 2001 D. Longest Max Min Subsequence(*1900) 思维
    CF2001D.LongestMaxMinSubsequence(*1900)思维题目链接题意:给你一个长度为\(n\)的序列\(a\),设\(S\)是\(a\)的所有可能的非空子序列的集合,且没有重复的元素。你的目标是找出\(S\)中最长的序列。如果有多个序列,请找出将奇数位置上的项乘以\(−1\)后,使词序最小......