日常---

Color with Occurrences

题意

在这里插入图片描述

思路

首先想到 D P DP DP的做法,我们构造 d p ( i ) dp(i) dp(i)表示位置 i i i上能够涂满红色的最小方案数,对于位置 i i i,我们遍历 m m m个匹配串,如果能成功匹配,就更新当前位置上的 d p dp dp值加一,并向前维护最小值。
运算出所有位置的dp值后,我们不断回溯 d p dp dp值减一所匹配的位置去匹配最长的可匹配子串并输出下标和位置即可
状态转移方程:
d p [ i ] = ( d p [ i − l e n ] + 1 , d p [ i ] ) dp[i] = (dp[i - len] + 1, dp[i]) dp[i]=(dp[ilen]+1,dp[i])

代码

void run () {
	cin >> P + 1 >> m;
	n = strlen(P + 1);
	rep (i, 1, m) cin >> s[i];

	mem(f, 0x3f);
	f[0] = 0;

	rep (i, 1, n) {
		rep (j, 1, m) {
			int len = SZ(s[j]);
			if(i >= len) {
				string tmp = "";
				rep (k, i - len + 1, i) tmp += P[k];
				if (tmp == s[j]) {
					f[i] = min(f[i], f[i - len] + 1);
					rep (k, 1, i - 1) f[k] = min(f[i], f[k]); 
				}
			}
		} 
	}
	if (f[n] == INF) TO(-1);
	else {
		int idx = f[n];
		cout << idx << endl;
		while (idx) {
			bool isOK = 0;
			for (int i = n; i >= 1 && !isOK; i -- ) {
				if (f[i] == idx && !isOK) {
					set<string> st;
					for (int j = 1; j <= m && !isOK; j ++ ) {
						int len = SZ(s[j]);
						string tmp = "";
						rep (k, i - len + 1, i) tmp += P[k];
						if (tmp == s[j]) st.insert(tmp);
					}
					int len = -1;
					for (auto it : st) len = max(len, SZ(it));
						
					for (int j = 1; j <= m && !isOK; j ++ ) {
						if (st.count(s[j]) && SZ(s[j]) == len) {
							cout << j << ' ' << i - len + 1 << endl;
							idx --;
							isOK = 1;
						}
					}

				}
			}
		}
	}
}	

题意

在这里插入图片描述
在这里插入图片描述

思路

本题我们只要预处理出每个前缀的b[i],之后对根节点到a[i]进行二分即可得到答案

代码

void dfs(int u, int p) {
    for (int i = h[u]; ~i ; i = ne[i]) {
        int j = e[i];
        if(j != p) {
        	s[j] = s[u] + a[i];
	        if(!v.size()) v.pb(b[i]);
	        else { int t = v.back(); v.pb(t + b[i]); }
	        res[j] = upper_bound(v.begin(), v.end(), s[j]) - v.begin()  ;
	        dfs(j, u);
	        v.pop_back();
        }
    }
}

void run() {
    cin >> n;
    rep (i, 2, n) {
        int u, x, y; cin >> u >> x >> y;
        add(u, x, y);
    }
    dfs(1, 0);
    rep (i, 2, n) cout << res[i] << " ";
    cout << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pale_B

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值