【无标题】


#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10;
int q[N], f[N], g[N];
int n, m;
/*
用一个单调对列来维护一个区间的最大值
*/
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		int v, w, s;
		cin >> v >> w >> s;
		//copy上一层的值
		memcpy(g, f, sizeof f);
		for (int j = 0; j < v; j++) {
			int tt = -1, hh = 0;
			for (int k = j; k <= m; k += v) {
				if (hh <= tt && k - q[hh] > s * v)hh++;//判断队头元素是否超出窗口范围
				//减去偏移量(发现每个窗口的体积依次递加,偏移量个数也依次递加,因此相减来抵消
				//队列q来维护每个f的值按依次递减顺序来维护
				while (hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w)tt--;
				q[++tt] = k;
				//对头一定是对最大的。
				f[k] = g[q[hh]] + (k - q[hh]) / v * w;
			}
		}
	}
	cout << f[m] << endl;
}

 

#include<bits/stdc++.h>
using namespace std;
using i16 = short;
using i32 = int;
using i64 = long long;
using u16 = unsigned short;
using u32 = unsigned;
using u64 = unsigned long long;
using f128 = long double;
using f64 = double;
using f32 = float;
const int maxn = 1e5 + 10;
const int INF = 1e9;
namespace list {
	typedef struct node {
		int data;//数据域
		node *next; //指针域
	} LNode, *LinkList; //LinkList是指向LNode类型数据的指针类型定义
	struct lklist {
		struct node;
		int size;
	};
	//初始化链表
	LinkList init_list() {
		LinkList L = new LNode;
		if (!L)
			return NULL;
		L->next = NULL; //指针域置空
		return L;
	}
	//打印链表
	void Printf_list(LinkList &L) {
		LinkList temp = L->next;
		while (temp != NULL) {
			cout << temp->data << "->";
			temp = temp->next;
		}
	}
	//插入数据(头插)
	void create_LinkList(LinkList &L, int n) {
		while (n--) {
			LinkList s = new LNode;
			cin >> s->data;
			s->next = L->next;
			L->next = s;
		}
	}
	//插入数据(尾插)
	void create_LinkList_back(LinkList &L, int n) {
		LinkList r = L;
		while (n--) {
			LinkList s = new LNode;
			cin >> s->data;
			s->next = NULL;
			r->next = s;
			r = s;
		}
	}
}
/*-------------------------------------------------------------*/
namespace segment_tree {
	// 节点数据结构
	struct node {
		int l, r;
		int val;
		int lazy;
	} t[maxn << 2];
	// 记录原始数据
	int a[maxn];
	// 建树
	void build(int u, int l, int r) {
		t[u].l = l;
		t[u].r = r;
		t[u].lazy = 0;
		if (l == r) {
			t[u].val = a[l];
			return;
		}
		int mid = (l + r) >> 1;
		build(u << 1, l, mid);
		build(u << 1 | 1, mid + 1, r);
		t[u].val = t[u << 1].val + t[u << 1 | 1].val;
	}
	// 更新子节点
	void pushdown(int u) {
		// 将lazy标记向下传给左右孩子节点
		t[u << 1].lazy += t[u].lazy;
		t[u << 1 | 1].lazy += t[u].lazy;
		// 更新左右孩子节点的值,为lazy标记×孩子节点表示的区间长度,记得减1
		t[u << 1].val += t[u].lazy * (t[u << 1].r - t[u << 1].l + 1);
		t[u << 1 | 1].val += t[u].lazy * (t[u << 1 | 1].r - t[u << 1 | 1].l + 1);
		// 清除该节点的lazy标记,防止重复更新
		t[u].lazy = 0;
	}
	// 更新父节点
	void pushup(int u) {
		t[u].val = t[u << 1].val + t[u << 1 | 1].val;
	}
	// 区间修改
	void modify(int u, int l, int r, int x) { // x为要求区间修改的值
		// 找到子区间,则不需要向下寻找
		if (l <= t[u].l && t[u].r <= r) {
			t[u].lazy += x;
			t[u].val += x * (t[u].r - t[u].l + 1);
			return;
		}
		// 若区间分布在节点表示的区间两侧,则分别查找左右孩子表示的区间
		int mid = (t[u].l + t[u].r) >> 1;
		// 需要查找孩子节点,要将lazy标记向下传递
		pushdown(u);
		if (l <= mid) modify(u << 1, l, r, x);
		if (mid < r) modify(u << 1 | 1, l, r, x);
		// 修改完成后要记得更新父节点的值
		pushup(u);
	}
	// 区间查询
	int query(int u, int L, int R) {
		// 若不在节点表示的区间内,则找不到
		if (t[u].l > R || t[u].r < L) return 0;
		// 若节点正好是要查询的子区间,则直接返回该节点的值
		if (t[u].l >= L && t[u].r <= R) return t[u].val;
		// 若要查找的区间分布在节点表示的区间两侧,则递归分别查找
		// 记得传递lazy标记,更新孩子节点的值
		pushdown(u);
		return query(u << 1, L, R) + query(u << 1 | 1, L, R);
	}
}
namespace kmp {
	void get_next(string t, int *next) {
		int i = 0, j = -1;
		next[i] = j;
		while (i < (int)t.length()) {
			if (j == -1 || t[i] == t[j]) {
				++i;
				++j;
				next[i] = j;
			} else {
				j = next[j];
			}
		}
	}
	//kmp算法,查找成功则返回起始位置,查找失败则返回-1
	int KMP(string str, string t) {
		int i = 0, j = 0;
		int *next = new int[t.length() + 1];
		get_next(t, next);
		while (i < (int)str.length() && j < (int)t.length()) {
			if (j == -1 || str[i] == t[j]) {
				++i;
				++j;
			} else
				j = next[j];
		}
		if (j == (int)t.length()) {
			return i - j;
		} else
			return -1;
	}
}
namespace treap {
	int na;
	int ch[maxn][2];//[i][0]代表i左儿子,[i][1]代表i右儿子
	int val[maxn], dat[maxn];
	int siz[maxn], cnt[maxn];
	int tot, root;
	int New(int v) { //新增节点,
		val[++tot] = v;//节点赋值
		dat[tot] = rand();//随机优先级
		siz[tot] = 1;//目前是新建叶子节点,所以子树大小为1
		cnt[tot] = 1;//新建节点同理副本数为1
		return tot;
	}
	void pushup(int id) { //和线段树的pushup更新一样
		siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + cnt[id];//本节点子树大小 = 左儿子子树大小 + 右儿子子树大小 + 本节点副本数
	}
	void build() {
		root = New(-INF), ch[root][1] = New(INF); //先加入正无穷和负无穷,便于之后操作(貌似不加也行)
		pushup(root);//因为INF > -INF,所以是右子树,
	}
	void Rotate(int &id, int d) { //id是引用传递,d(irection)为旋转方向,0为左旋,1为右旋
		int temp = ch[id][d ^ 1];//旋转理解:找个动图看一看就好(或参见其他OIer的blog)
		ch[id][d ^ 1] = ch[temp][d];//这里讲一个记忆技巧,这些数据都是被记录后马上修改
		ch[temp][d] = id;//所以像“Z”一样
		id = temp;//比如这个id,在上一行才被记录过,ch[temp][d]、ch[id][d ^ 1]也是一样的
		pushup(ch[id][d]), pushup(id); //旋转以后size会改变,看图就会发现只更新自己和转上来的点,pushup一下,注意先子节点再父节点
	}//旋转实质是({在满足BST的性质的基础上比较优先级}通过交换本节点和其某个叶子节点)把链叉开成二叉形状(从而控制深度),可以看图理解一下
	void insert(int &id, int v) { //id依然是引用,在新建节点时可以体现
		if (!id) {
			id = New(v);//若节点为空,则新建一个节点
			return ;
		}
		if (v == val[id])cnt[id]++; //若节点已存在,则副本数++;
		else { //要满足BST性质,小于插到左边,大于插到右边
			int d = v < val[id] ? 0 : 1;//这个d是方向的意思,按照BST的性质,小于本节点则向左,大于向右
			insert(ch[id][d], v); //递归实现
			if (dat[id] < dat[ch[id][d]])Rotate(id, d ^ 1); //(参考一下图)与左节点交换右旋,与右节点交换左旋
		}
		pushup(id);//现在更新一下本节点的信息
	}
	void Remove(int &id, int v) { //最难de部分了
		if (!id)return ; //到这了发现查不到这个节点,该点不存在,直接返回
		if (v == val[id]) { //检索到了这个值
			if (cnt[id] > 1) {
				cnt[id]--, pushup(id);    //若副本不止一个,减去一个就好
				return ;
			}
			if (ch[id][0] || ch[id][1]) { //发现只有一个值,且有儿子节点,我们只能把值旋转到底部删除
				if (!ch[id][1] || dat[ch[id][0]] > dat[ch[id][1]]) { //当前点被移走之后,会有一个新的点补上来(左儿子或右儿子),按照优先级,优先级大的补上来
					Rotate(id, 1), Remove(ch[id][1], v); //我们会发现,右旋是与左儿子交换,当前点变成右节点;左旋则是与右儿子交换,当前点变为左节点
				} else Rotate(id, 0), Remove(ch[id][0], v);
				pushup(id);
			} else id = 0; //发现本节点是叶子节点,直接删除
			return ;//这个return对应的是检索到值de所有情况
		}
		v < val[id] ? Remove(ch[id][0], v) : Remove(ch[id][1], v); //继续BST性质
		pushup(id);
	}
	int get_rank(int id, int v) {
		if (!id)return 1; //若查询值不存在,返回;因为最后要减一排除哨兵节点,想要结果为-1这里就返回0
		if (v == val[id])return siz[ch[id][0]] + 1; //查询到该值,由BST性质可知:该点左边值都比该点的值(查询值)小,故rank为左儿子大小 + 1
		else if (v < val[id])return get_rank(ch[id][0], v); //发现需查询的点在该点左边,往左边递归查询
		else return siz[ch[id][0]] + cnt[id] + get_rank(ch[id][1], v); //若查询值大于该点值。说明询问点在当前点的右侧,且此点的值都小于查询值,所以要加上cnt[id]
	}
	int get_val(int id, int rank) {
		if (!id)return INF; //一直向右找找不到,说明是正无穷
		if (rank <= siz[ch[id][0]])return get_val(ch[id][0], rank); //左边排名已经大于rank了,说明rank对应的值在左儿子那里
		else if (rank <= siz[ch[id][0]] + cnt[id])return val[id]; //上一步排除了在左区间的情况,若是rank在左与中(目前节点)中,则直接返回目前节点(中区间)的值
		else return get_val(ch[id][1], rank - siz[ch[id][0]] - cnt[id]); //剩下只能在右区间找了,rank减去左区间大小和中区间,继续递归
	}
	int get_pre(int v) {
		int id = root, pre; //递归不好返回,以循环求解
		while (id) { //查到节点不存在为止
			if (val[id] < v)pre = val[id], id = ch[id][1]; //满足当前节点比目标小,往当前节点的右侧寻找最优值
			else id = ch[id][0];//无论是比目标节点大还是等于目标节点,都不满足前驱条件,应往更小处靠近
		}
		return pre;
	}
	int get_next(int v) {
		int id = root, next;
		while (id) {
			if (val[id] > v)next = val[id], id = ch[id][0]; //同理,满足条件向左寻找更小解(也就是最优解)
			else id = ch[id][1];//与上方同理
		}
		return next;
	}
}
namespace Scapegoat_Tree {
	const double alpha = 0.7;
	struct node {
		node *l, *r;
		int val, size, cnt;
		bool deleted;
		bool isbad() {
			return l->cnt > alpha * cnt + 5 || r->cnt > alpha * cnt + 5;
		}
		void maintain() {
			size = !deleted + l->size + r->size;
			cnt = 1 + l->cnt + r->cnt;
		}
	};
	node *null;
	void dfs(node *o, vector<node *> &v) {
		if (o == null)return;
		dfs(o->l, v);
		if (!o->deleted)v.push_back(o);
		dfs(o->r, v);
		if (o->deleted)delete o;
	}
	node *build(vector<node *> &v, int l, int r) {
		if (l >= r)return null;
		int mid = (l + r) >> 1;
		node *o = v[mid];
		o->l = build(v, l, mid);
		o->r = build(v, mid + 1, r);
		o->maintain();
		return o;
	}
	void rebuild(node *&o) {
		vector<node *> v;
		dfs(o, v);
		o = build(v, 0, v.size());
	}
	void insert(int x, node *&o) {
		if (o == null) {
			o = new node;
			o->l = o->r = null;
			o->deleted = false;
			o->size = o->cnt = 1;
			o->val = x;
			return;
		} else {
			++o->size;
			++o->cnt;
			if (x >= o->val)
				insert(x, o->r);
			else
				insert(x, o->l);
			if (o->isbad())rebuild(o);
		}
	}
	int rank(node *now, int x) {
		int ans = 1;
		while (now != null) {
			if (now->val >= x)now = now->l;
			else {
				ans += now->l->size + !now->deleted;
				now = now->r;
			}
		}
		return ans;
	}
	int kth(node *now, int x) {
		while (now != null) {
			if (!now->deleted && now->l->size + 1 == x)
				return now->val;
			if (now->l->size >= x)now = now->l;
			else {
				x -= now->l->size + !now->deleted;
				now = now->r;
			}
		}
	}
	void erase(node *o, int rk) {
		if (!o->deleted && rk == o->l->size + 1) {
			o->deleted = 1;
			--o->size;
			return;
		}
		--o->size;
		if (rk <= o->l->size + !o->deleted)
			erase(o->l, rk);
		else
			erase(o->r, rk - o->l->size - !o->deleted);
	}
	node *root;
	void main() {
		null = new node;
		root = null;
//	        int n;
//	        scanf("%d",&n);
//	        while(n--)
//	        {
//	            int op,x;
//	            scanf("%d%d",&op,&x);
//	            if(op==1)insert(x,root);
//	            if(op==2)erase(root,rank(root,x));
//	            if(op==3)printf("%d\n",rank(root,x));
//	            if(op==4)printf("%d\n",kth(root,x));
//	            if(op==5)printf("%d\n",kth(root,rank(root,x)-1));
//	            if(op==6)printf("%d\n",kth(root,rank(root,x+1)));
//	        }
	}
}
namespace dijkstra {
	typedef pair<int, int> PII;
#define N maxn
	int n, m;
	int h[N], e[N], ne[N], w[N], idx;
	int dist[N];
	bool st[N]; // 被确定最短路的点集合
	void add(int a, int b, int c) {
		e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
	}
	void dijkstra() {
		memset(dist, 0x3f, sizeof dist);
		dist[1] = 0;
		priority_queue<PII, vector<PII>, greater<PII>> heap;
		heap.push({0, 1});
		while (heap.size()) {
			auto t = heap.top();
			heap.pop();
			int ver = t.second;
			if (st[ver]) continue;
			st[ver] = true;
			for (int i = h[ver]; i != -1; i = ne[i]) {
				int j = e[i];
				if (dist[j] > dist[ver] + w[i]) { // 邻接边的距离大于用当前点更新的距离时就替换
					dist[j] = dist[ver] + w[i];// d[ver] 是当前最小点的距离; w[i] 是当前邻接边的权重
					heap.push({dist[j], j});
				}
			}
		}
	}
	inline void init() {
		memset(h, -1, sizeof h);
	}
}
namespace spfa {
	int n, m;
	int h[N], e[N], ne[N], w[N], idx;
	int dist[N];
	bool st[N];
	void add(int a, int b, int c) {
		e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
	}
	void spfa() {
		memset(dist, 0x3f, sizeof dist);
		dist[1] = 0;
		queue<int> q;
		q.push(1);
		st[1] = true;
		while (q.size()) {
			int t = q.front();
			q.pop();
			st[t] = false;
			for (int i = h[t]; i != -1; i = ne[i]) {
				int j = e[i];
				if (dist[j] > dist[t] + w[i]) {
					dist[j] = dist[t] + w[i];
					if (!st[j]) {
						st[j] = true;
						q.push(j);
					}
				}
			}
		}
	}
#undef N
}
namespace gaosi_xiaoyuan_fa {
	double map[111][111];
	double ans[111];
	double eps = 1e-7;
	void main() {
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n + 1; j++)
				scanf("%lf", &map[i][j]);
		for (int i = 1; i <= n; i++) {
			int r = i;
			for (int j = i + 1; j <= n; j++)
				if (fabs(map[r][i]) < fabs(map[j][i]))
					r = j; //find_the_biggest_number_of_the_first_column(at present)
			if (fabs(map[r][i]) < eps) {
				printf("No Solution");
				return ;
			}
			if (i != r)swap(map[i], map[r]); //对换一行或一列,属于找最大当前系数的其中一步。(这样就可以只处理当前行的系数啦!)
			double div = map[i][i];
			for (int j = i; j <= n + 1; j++)
				map[i][j] /= div;
			for (int j = i + 1; j <= n; j++) {
				div = map[j][i];
				for (int k = i; k <= n + 1; k++)
					map[j][k] -= map[i][k] * div;
			}
		}
		ans[n] = map[n][n + 1];
		for (int i = n - 1; i >= 1; i--) {
			ans[i] = map[i][n + 1];
			for (int j = i + 1; j <= n; j++)
				ans[i] -= (map[i][j] * ans[j]);
		}//回带操作
		for (int i = 1; i <= n; i++)
			printf("%.2lf\n", ans[i]);
	}
}
//希尔排序
//不稳定排序
void ShellSort(int *item, int n) {
	int gap = n / 2;
	while (gap >= 1) {
		int t = gap;
		int pos = 0;
		while (t--) {
			for (int i = pos; i < n; i += gap) {
				for (int k = pos; k < n - gap; k += gap) {
					if (item[k] <= item[k + gap]) {
						int m = item[k];
						item[k] = item[k + gap];
						item[k + gap] = m;
					}
				}
			}
			pos++;
		}
		//每趟排序完输出一次结果
		for (int i = 0; i < n; i++) {
			cout << item[i] << " ";
		}
		cout << endl;
		gap = gap / 2;
	}
}
void SelectSort(int *item, int n) {
	int minv, maxv;
	for (int i = 0,  j = n; i < j; ++i, --j) {
		minv = i;
		maxv = j;
		for (int k = i + 1; k < n; k++) {
			if (item[k] < item[minv])minv = k;
			if (item[k] > item[maxv])maxv = k;
		}
		swap(item[i], item[minv]);
		swap(item[j], item[maxv]);
	}
}
int getPivotkey(int *item, int low, int high) {
	int key = item[low];
	while (low < high) {
		while (low < high && item[high] >= key) {
			high--;
		}
		if (low < high) {
			item[low] = item[high];
		}
		while (low < high && item[low] <= key) {
			low++;
		}
		if (low < high) {
			item[high] = item[low];
		}
	}
	item[low] = key;
	return low;
}
//快速排序
//不稳定排序
void QuickSort(int *item, int low, int high) {
	if (high - low <=  32)SelectSort(item + low, high - low +  1);
	if (low <= high) {
		int pivotkey = getPivotkey(item, low, high);
		cout << item[pivotkey] << " " << pivotkey + 1 << endl;
		QuickSort(item, low, pivotkey - 1);
		QuickSort(item, pivotkey + 1, high);
	}
}
int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值