疑似本题最神秘的错误
查看原帖
疑似本题最神秘的错误
482610
Mortidesperatslav楼主2025/1/5 20:55

民间数据 50pts,官方数据 55pts,洛谷民间数据最后 10 个点和官方数据 #11~19 RE,但是发给 Mrkn_chenyx12 能过官方数据 #19。

讨论区各种 Hack 对于我的代码全部无效,只有 n3n \ge 3 的大数据才能够卡掉。

经过分析发现是试图将元素放入空栈时发现没有空栈,然而我检测了代码逻辑发现我在每次操作后都保证了空栈的存在。

求救,代码如下,加了注释:

#include<bits/stdc++.h>
using namespace std;
deque<int> stk[305];
int t, n, m, k, pos, nxt, a[2000005], buk[2005], ins[2005];
set<int> siz[20];
struct operator_{
	int op, u, v;
};
queue<operator_> operator__;
void gensiz(int u, int lsz){//更新一个栈的大小 
	if (siz[lsz].find(u) == siz[lsz].end())
		exit(3256);
	siz[lsz].erase(u);
	siz[stk[u].size()].insert(u);
}
void print(int u){
	cerr << u << "(" << stk[u].size() << "):";
	if (stk[u].empty()){
		cout << "\n";
		return;
	}
	cerr << stk[u].front() << " " << stk[u].back() << "\n";
}
void printall(){
	for (int i = 1; i <= n; i++)
		print(i);
}
void stk_ins(int u, int x){//插入元素 
	int lu = stk[u].size();
//	cerr << "1 " << u << "\n";
	operator__.push({1, u, 0});
	stk[u].push_back(x);
	ins[x] = u;
	gensiz(u, lu);
}
void c_bottom(int u, int v){//底部消除 
//	cerr << "2 " << u << " " << v << "\n";
	operator__.push({2, u, v});
	if (stk[u].empty() || stk[v].empty())
		exit(325609);
	if (stk[u].front() != stk[v].front())
		exit(3256090);
	int lu = stk[u].size(), lv = stk[v].size();
	ins[stk[u].front()] = -1;
	stk[u].pop_front();
	stk[v].pop_front();
	gensiz(u, lu);
	gensiz(v, lv);
}
void c_top(int u, bool op = 1){//顶部连续两张牌相同 
	if (stk[u].size() < 2)
		exit(32560900);
	int lu = stk[u].size();
	int x = stk[u].back();
	if (op)
		ins[x] = -1;
	stk[u].pop_back();
	int y = stk[u].back();
	stk[u].pop_back();
	if (x != y)
		exit(325609000);
	gensiz(u, lu);
}
void op1_1(int x){//策略 1-1:至少两个栈为空的情况 
	if (ins[x] == -1){//该元素未入栈,直接放入空栈 
		int ppos = *siz[0].begin();
		stk_ins(ppos, x);
	}else{
		if (stk[ins[x]].back() == x){//在顶部,放到顶部然后弹出 
			stk_ins(ins[x], x);
			c_top(ins[x]);
		}else if (stk[ins[x]].front() == x){//在底部,放入空栈底部然后消去 
			int tins = ins[x];
			int ppos = *siz[0].begin();
			stk_ins(ppos, x);
			c_bottom(ppos, tins);
		}
	}
}
void op1_2(int x){//策略 1-2:只有一个栈为空,且至少有一个栈元素个数为 1 
//	cerr << x << "\n";
	if (ins[x] == -1){//该元素未入栈,放入元素个数为 1 的栈 
		int ppos = *siz[1].begin();
		stk_ins(ppos, x);
	}else{
		if (stk[ins[x]].back() == x){//在顶部,放到栈顶弹出 
			stk_ins(ins[x], x);
			c_top(ins[x]);
		}else if (stk[ins[x]].front() == x){//在底部,放到空栈栈底消去 
			int tins = ins[x];
			int ppos = *siz[0].begin();
			stk_ins(ppos, x);
			c_bottom(ppos, tins);
		}
	}
}
int op2(int pos, int x){
	if (ins[x] == -1){
		if (a[pos + 1] == x){//连续两张相同,直接消掉  
			int ppos = *siz[0].begin();
			stk_ins(ppos, x);
			stk_ins(ppos, x);
			c_top(ppos);
			return pos + 1;
		}else{
			int op = 0, id = 0;
			for (int i = pos + 1; i <= m; i++){
				if (a[i] == x){//目标与当前元素相同 
					id = i;
					op = 1;
					break;
				}else if (stk[ins[a[i]]].front() == a[i]){//目标是栈底元素 
					id = i;
					op = 2;
					break;
				}
			}
			if (op == 1){//目标与当前元素相同 
				int ppos = *siz[0].begin();
				stk_ins(ppos, x);
				for (int i = pos + 1; i <= id; i++){
					if (ins[a[i]] == -1){//当前元素没出现过,放到空闲的栈 
						if (siz[1].size()){ 
							int targ = *siz[1].begin();
							if (targ == ppos)
								targ = *(++siz[1].begin());
							stk_ins(targ, a[i]);
						}
						continue;
					}
					if (stk[ins[a[i]]].back() == a[i]){//消掉 
						stk_ins(ins[a[i]], a[i]);
						c_top(ins[a[i]]);
					}
				}
				return id;
			}else{
				int cnt = 0;
				for (int i = pos + 1; i < id; i++){//统计对应栈顶元素个数 
					if (a[i] == stk[ins[a[id]]].back())
						cnt++;
				}
				if (cnt & 1){//如果为奇数,新元素放空栈,最后从上面消栈底元素 
					int ppos = *siz[0].begin();
					stk_ins(ppos, x);
					for (int i = pos + 1; i <= id; i++){
						if (ins[a[i]] == -1){
							if (siz[1].size()){
								int targ = *siz[1].begin();
								if (targ == ppos)
									targ = *(++siz[1].begin());
								stk_ins(targ, a[i]);
							}else if (siz[0].size()){
								int targ = *siz[0].begin();
								stk_ins(targ, a[i]);
							}
							continue;
						}
						if (stk[ins[a[i]]].back() == a[i]){
							stk_ins(ins[a[i]], a[i]);
							c_top(ins[a[i]]);
						}
					}
					return id;
				}else{//如果为偶数,新元素放栈顶,最后从底部消 
					int ppos = ins[a[id]];
					int ntop = stk[ins[a[id]]].back();
					stk_ins(ppos, x);
					for (int i = pos + 1; i < id; i++){
						if (a[i] == ntop){
							if (stk[ppos].back() == ntop){
								stk_ins(ins[a[i]], a[i]);
								c_top(ins[a[i]], 0);
							}else
								stk_ins(ppos, a[i]);
							continue;
						}
						if (ins[a[i]] == -1){
							if (siz[1].size()){
								int targ = *siz[1].begin();
								stk_ins(targ, a[i]);
							}
						}else{
							stk_ins(ins[a[i]], a[i]);
							c_top(ins[a[i]]);
						}
					}
					int ppos2 = *siz[0].begin(), tins = ins[a[id]];
					stk_ins(ppos2, a[id]);
					c_bottom(tins, ppos2);
					return id;
				}
			}
		}
	}else{
		if (stk[ins[x]].back() == x){//消除顶部 
			stk_ins(ins[x], x);
			c_top(ins[x]);
		}else{//消除底部 
			int tins = ins[x];
			int ppos = *siz[0].begin();
			stk_ins(ppos, x);
			c_bottom(ppos, tins);
		}
		return pos;
	}
}
int work(int pos){
	if (siz[0].size() > 1)//两个空栈 
		op1_1(a[pos]);
	else if (siz[0].size() == 1 && siz[1].size())//一个空栈和一个只有一个元素的栈 
		op1_2(a[pos]);
	else//一个空栈 
		return op2(pos, a[pos]);
	return 0;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin >> t;
	while (t--){
		cin >> n >> m >> k;
		for (int i = 1; i <= k; i++)//初始化 
			buk[a[i]] = 0;
		for (int i = 0; i <= 15; i++)
			siz[i].clear();
		for (int i = 1; i <= n; i++){
			while (!stk[i].empty())
				stk[i].pop_front();
			siz[0].insert(i);
		}
		for (int i = 1; i <= m; i++){
			cin >> a[i];
			buk[a[i]]++;
			ins[a[i]] = -1;
		}
		for (int i = 1; i <= m; i++){//进行操作 
			int res = work(i);
			if (res)
				i = res;
		//	cerr << i << "\n";
		//	printall();
		//	cerr << "\n";
		//	for (int j = 1; j <= n; j++){
		//		cout << j << ":";
		//		cout << stk[j].size() << " ";
		//		if (stk[j].size() == 1)
		//			cout << stk[j].front();
		//		else if (stk[j].size() == 2)
		//			cout << stk[j].front() << " " << stk[j].back();
		//		cout << "\n";
		//	}
		}
		cout << operator__.size() << "\n";//输出解 
		while (!operator__.empty()){
			operator_ tmp = operator__.front();
			operator__.pop();
			if (tmp.op == 1)
				cout << 1 << " " << tmp.u << "\n";
			else
				cout << 2 << " " << tmp.u << " " << tmp.v << "\n";
		}
	}
	return 0;
}
2025/1/5 20:55
加载中...