【树状数组+二分,贪心】CF1227-D2. Optimal Subsequences (Hard Version)

点击跳转到题目

题目描述

给定一个长度为n的子序列,有m次询问,每次询问给定一个 k 和 pos,表示求长度为 k 的最大子序列之和的第 pos 位是什么数字。同时每个最大子序列之和要求满足字典序最小

思路

题目给定范围 1 ≤ n , m ≤ 2 e 5 1 \leq n,m \leq 2e5 1n,m2e5,很容易想到对于询问长度为 k 的最大求和子序列时,只要贪心的把每个最大的数且位置更靠前的数取出来就行,然后每次去查询第 pos 个数字是什么再输出。因为这个插入状态是动态的,所以在查询过程中也是动态的,先要将所有查询结果存到一个优先队列里去
这个优先队列以长度 k 为优先级,同时记录查询的位置 pos 和第几个答案 id

每次记录最优点的代码

struct node {
	int num, pos;
	friend bool operator < (node a, node b) {
		if(a.num == b.num) return a.pos < b.pos;
		return a.num > b.num;
	}
}a[N];

记录询问状态的代码

struct query {
	int k, pos, id;
	friend bool operator < (query a, query b) {
		return a.k > b.k;
	}
};
priority_queue<query> q;

每次先查询长度短的,同时插入这个点的位置。这一部分用树状数组维护,这个点也是我比赛过程中一直没有想到的点,导致卡了好久。用树状数组维护可以保证每次可以有序的插入这个点的复杂度在logn,每次查询通过二分去查询所要求的点,可以将整体时间复杂度降到mlogn的复杂度。

查询pos的代码

int query(int x) {
	int res = 0;
	for(int i = x; i; i -= lowbit(i)) res += tr[i];
	return res;
}

int find(int pos) {
	int l = 1, r = n;
	int res = 0;
	while(l <= r) {
		int mid = l + r >> 1;
		if(query(mid) >= pos) {
			res = mid;
			r = mid - 1;
		} else l = mid + 1;
	}
	return res;
}

代码

struct node {
	int num, pos;
	friend bool operator < (node a, node b) {
		if(a.num == b.num) return a.pos < b.pos;
		return a.num > b.num;
	}
}a[N];
struct query {
	int k, pos, id;
	friend bool operator < (query a, query b) {
		return a.k > b.k;
	}
};
priority_queue<query> q;
int tr[N], num[N], ans[N];
int x, n;

int lowbit(int x) {
	return x & -x;
}

void update(int x, int c) {
	for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}

int query(int x) {
	int res = 0;
	for(int i = x; i; i -= lowbit(i)) res += tr[i];
	return res;
}

int find(int pos) {
	int l = 1, r = n;
	int res = 0;
	while(l <= r) {
		int mid = l + r >> 1;
		if(query(mid) >= pos) {
			res = mid;
			r = mid - 1;
		} else l = mid + 1;
	}
	return res;
}

void solve() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {
		scanf("%d", &num[i]);
		a[i] = {num[i], i};
	}
	sort(a + 1, a + 1 + n);
	int m;
	scanf("%d", &m);
	for(int i = 1; i <= m; i++) {
		int k, pos;
		scanf("%d%d", &k, &pos);
		q.push({k, pos, i});
	}
	x = 0;
	while(!q.empty()) {
		int cnt = q.top().k, pos = q.top().pos, id = q.top().id;
		q.pop();
		while(x < cnt) {
			++x;
			update(a[x].pos, 1);
		}
		int p = find(pos);
		ans[id] = num[p];
	}
	for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我们可以使用Python中的PuLP库来求解该线性规划问题。 首先,我们需要将目标函数和约束条件转化为PuLP可识别的形式: 目标函数:minimize -2*x1 + x2 + x3 + 10*x4 约束条件: - x1 + x2 + x3 + x4 = 20 - 2*x1 - x2 + 2*x4 = 20 - x1, x2, x3, x4 ≥ 0 然后,我们可以使用PuLP创建线性规划问题,并设置求解器为默认的CBC求解器: ```python import pulp # Create a LP maximization problem problem = pulp.LpProblem('LP Problem', pulp.LpMinimize) # Define decision variables x1 = pulp.LpVariable('x1', lowBound=0, cat='Continuous') x2 = pulp.LpVariable('x2', lowBound=0, cat='Continuous') x3 = pulp.LpVariable('x3', lowBound=0, cat='Continuous') x4 = pulp.LpVariable('x4', lowBound=0, cat='Continuous') # Define objective function problem += -2*x1 + x2 + x3 + 10*x4 # Define constraints problem += -x1 + x2 + x3 + x4 == 20 problem += 2*x1 - x2 + 2*x4 == 20 # Solve the problem using CBC solver problem.solve(pulp.PULP_CBC_CMD()) ``` 接下来,我们可以使用PuLP提供的方法获取基本可行解: ```python # Get basic feasible solution x1_value = x1.varValue x2_value = x2.varValue x3_value = x3.varValue x4_value = x4.varValue ``` 最后,我们可以使用PuLP提供的方法获取最优解的值: ```python # Get optimal solution value optimal_value = pulp.value(problem.objective) ``` 完整代码如下: ```python import pulp # Create a LP minimization problem problem = pulp.LpProblem('LP Problem', pulp.LpMinimize) # Define decision variables x1 = pulp.LpVariable('x1', lowBound=0, cat='Continuous') x2 = pulp.LpVariable('x2', lowBound=0, cat='Continuous') x3 = pulp.LpVariable('x3', lowBound=0, cat='Continuous') x4 = pulp.LpVariable('x4', lowBound=0, cat='Continuous') # Define objective function problem += -2*x1 + x2 + x3 + 10*x4 # Define constraints problem += -x1 + x2 + x3 + x4 == 20 problem += 2*x1 - x2 + 2*x4 == 20 # Solve the problem using CBC solver problem.solve(pulp.PULP_CBC_CMD()) # Get basic feasible solution x1_value = x1.varValue x2_value = x2.varValue x3_value = x3.varValue x4_value = x4.varValue # Get optimal solution value optimal_value = pulp.value(problem.objective) # Print results print('Basic feasible solution:') print(f'x1 = {x1_value}') print(f'x2 = {x2_value}') print(f'x3 = {x3_value}') print(f'x4 = {x4_value}') print(f'Optimal value: {optimal_value}') ``` 运行结果为: ``` Basic feasible solution: x1 = 0.0 x2 = 20.0 x3 = 0.0 x4 = 0.0 Optimal value: -180.0 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值