过样例但WA求助
查看原帖
过样例但WA求助
753077
adfsc123楼主2024/1/23 08:59

线段树+循环单点修改,本地IDE debug逻辑没问题,自己造的数据也都没问题

#include<iostream>
#include<vector>
#include<math.h>
#include<set>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
/*线段树(segment Tree)是一种树状数组,用于区间操作。
* 结构为完全二叉树,结点值是区间之和
* 根结点为整个区间,左子树为左半区间,右子树为右区间
*/

/*
* 区间修改懒标记的思想是:将修改效果全部施加到公共父结点上,但不修改子结点
* 只有当访问子结点时,将懒标记下传并修改值
* 例如,修改区间[L,R]所有元素
* 找到所有完全包含于[L,R]的尽可能上层的所有子结点,即最大分割
* 将这些结点懒标记
*/

//线段树结点
class segmentTreeNode {
public:
	//线段左右端点
	int start;
	int end;
	//结点值,可以存储区间相关的一些属性,如最值、求和等
	//这里以取最大值为例
	int data;
	//延迟更新标记
	int mark;
	segmentTreeNode* left;
	segmentTreeNode* right;
	segmentTreeNode(int start, int end, int data) {
		this->start = start;
		this->end = end;
		this->data = data;
		this->left = this->right = nullptr;
		this->mark = 0;
	}

	void outPut() {
		cout << "区间:" << this->start << "~" << this->end <<",";
		cout << "\t" << "val=" << this->data <<"\t" <<endl;
	}
	



};

//线段树
class segmentTree {
private:
	segmentTreeNode* treeBulider(int left, int right) {
		if (left > right) return nullptr;
		else if (left == right) {
			return new segmentTreeNode(left, right, vec[left]);
		}
		else {
			int mid = (left + right) >> 1;
			segmentTreeNode* subRoot = new segmentTreeNode(left, right, 0);
			subRoot->left = treeBulider(left, mid);
			subRoot->right = treeBulider(mid + 1, right);
			subRoot->data = min(subRoot->left->data, subRoot->right->data); //pushUp操作
			return subRoot;
		}
	}




public:
	vector<int> vec;
	segmentTreeNode* root;
	segmentTree(vector<int> vec, int start, int end) {
		this->vec = vec;
		this->root = treeBulider(start, end);
	}

	//可视化
	void show() {
		queue<segmentTreeNode*> Q;
		Q.push(this->root);
		segmentTreeNode* curNode = nullptr;
		//记录层数
		int count = 1;
		while (!Q.empty()) {
			//记录结点数
			int size = Q.size();
			//同一层
			cout << "第" << count << "层" << endl;
			while (size-- > 0) {
				curNode = Q.front();
				curNode->outPut();
				Q.pop();
				if (curNode->left)Q.push(curNode->left);
				if (curNode->right) Q.push(curNode->right);
			}
			//换层
			count++;
		}
	}




	//单点修改
	void changOne(segmentTreeNode* root,int pos,int newVal) {
		//不在当前区间
		if (pos<root->start || pos>root->end) return;
		//在当前点
		if (root->start == root->end&&root->start==pos) {
			root->data = newVal;
			this->vec[pos] = newVal;
			return;
		}
		int mid = (root->start + root->end) >> 1;
		if(pos>mid) changOne(root->right, pos, newVal);
		else changOne(root->left, pos, newVal);
		//passUp
		root->data = min(root->left->data, root->right->data);


	}


	//区间查找
	int queryMin(int start, int end, segmentTreeNode* root) {
		//正好覆盖
		if (root->start >= start && root->end <= end)
			return root->data;
		if (root->start > end || root->end < start)
			return 9999999;
		//每当查询到任一个结点,懒标记下传
		//pushdown(root);
		//当前查询区间中点
		int mid = (root->start + root->end) >> 1;
		int ll = 9999999, rr = 9999999;
		//与左侧区间有交点
		if (start <= mid) {
			ll = queryMin(start, end, root->left);
		}
		if (end > mid)
			rr = queryMin(start, end, root->right);
		return min(ll, rr);
	}





};


int main() {
	int n = 0, m = 0;
	cin >> n >> m;
	vector<int> classrooms(n + 1);
	for (int i = 1; i <= n; i++) {
		cin >> classrooms[i];
	}
	vector<vector<int>> vec(m+1,vector<int>(3));
	for (int i = 1; i <= m; i++) {
		for (int j = 0; j < 3; j++) {
			cin >> vec[i][j];
		}
	}
	segmentTree* tree = new segmentTree(classrooms, 1, n);
	for (int i = 1; i <= m; i++) {
		int st = vec[i][1], ed = vec[i][2], qu = vec[i][0];
		int mins = tree->queryMin(st, ed, tree->root);
		cout << i<<"订单" << endl;
		tree->show();
		if (mins < qu) {
			cout << -1 << endl;
			cout << i;
			return 0;
		}
		
		for (int j = st; j <= ed; j++) {
			classrooms[j] -= qu;
			tree->changOne(tree->root, j, classrooms[j]);
		}
		
		
		cout << endl;
	}
	cout << 0;
	return 0;
}
2024/1/23 08:59
加载中...