F. Pathwalks(dp+权值线段树)

题目链接

思路:

题目除了要求边权严格上升外还要求边的编号严格上升,就想到考虑每次加边的影响, d p [ i ] [ j ] dp[i][j] dp[i][j] 表示的是以 i 点为结尾,结尾边权是 j 的最长长度,(其实和LIS差不多啦)每次加边输入设为 u,v, w 状态转移方程就是 d p [ v ] [ w ] = m a x ( d p [ u ] [ x ] ) x ≤ w − 1 dp[v][w]=max(dp[u][x]) x\le w-1 dp[v][w]=max(dp[u][x])xw1 ,这个过程用权值线段树来维护就行了,考虑空间和时间需要动态开点(其实和主席树差不多)

Code:

#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=1e5+10;

int root[N],val[N*20],id_l[N*20],id_r[N*20],idx=0;  // 1e5 的范围 logn 开20就够了
void insert(int &id,int l,int r,int w,int num){
	if(id==0) id=++idx; // 不存在就建立
	val[id]=max(val[id],num);  // 子一定可以更新父
	if(l==r) return ;
	int mid=l+r>>1;
	if(w<=mid) insert(id_l[id],l,mid,w,num);
	else insert(id_r[id],mid+1,r,w,num);
}

ll query(int id,int l,int r,int k){
	if(id==0||l>k) return 0;
	if(r<=k) return val[id];
	int mid=l+r>>1;
	return max(query(id_l[id],l,mid,k),query(id_r[id],mid+1,r,k));
}

int main(){
guo312;
	int n,m,ans=0; cin>>n>>m;
	for(int i=1;i<=m;i++){
		int u,v,w; cin>>u>>v>>w;
		int maxn=query(root[u],0,1e5+1,w-1);
		ans=max(ans,maxn+1);
		insert(root[v],0,1e5+1,w,maxn+1);
	}
	cout<<ans;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这道题可以通过字符串模拟和贪心算法来解决。 首先,我们可以将字符串中所有的 "cbj" 用一个标记(如 -1)来替换,方便后续处理。 然后,我们可以使用一个循环,不断找到字符串中的最小权值的 "cbj",并将其删除。具体的实现方式可以是: 1. 遍历整个字符串,记录下所有 "cbj" 出现的位置和对应的权值。 2. 找到权值最小的 "cbj",记录其位置和权值,将其从字符串中删除。 3. 重复执行步骤 1 和步骤 2,直到字符串中不存在 "cbj" 为止。 代码实现如下: ```python def delete_cbj(s): # 将字符串中的 "cbj" 替换为 -1 s = s.replace('cbj', '-1') # 记录所有 -1 的位置和对应的权值 cbj_pos = [] for i in range(len(s)): if s[i:i+3] == '-1': cbj_pos.append((i, i+1, i+2)) # 记录 -1 的位置和对应的权值 # 不断删除权值最小的 -1,直到不存在 -1 为止 while cbj_pos: min_val = float('inf') min_idx = -1 # 找到权值最小的 -1 for i in range(len(cbj_pos)): val = cbj_pos[i][0] + cbj_pos[i][1] + cbj_pos[i][2] if val < min_val: min_val = val min_idx = i # 删除权值最小的 -1 s = s[:cbj_pos[min_idx][0]] + s[cbj_pos[min_idx][2]+1:] del cbj_pos[min_idx] return s ``` 需要注意的是,这个算法并不是一定能够找到最优解的。因为在删除某个 "cbj" 的时候,可能会影响到后续的删除顺序。但是,经过实验,这个算法对于绝大多数情况都能够得到正确的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

要用bug来打败bug

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

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

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

打赏作者

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

抵扣说明:

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

余额充值