社区讨论

求调

P8866[NOIP2022] 喵了个喵参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mi4rdzrr
此快照首次捕获于
2025/11/18 23:59
4 个月前
此快照最后确认于
2025/11/20 04:04
4 个月前
查看原帖
35 pts,其余全部 RE。
过了讨论区所有 hack+CCF 大样例共 60 组数据(多测拆开,没有验证正确性,只是确保了不 RE),对拍 1k+ 组数据无 RE(对拍数据范围:n10n\leq 10k=2×n1k=2\times n-1,每种卡牌出现次数为 [2,10][2,10] 中的偶数,由此可得 m190m \leq 190)。
思路与题解第一篇一致。代码中 pos 的定义有点奇怪,第 ii 个栈两个 pos 分别是 i×2i\times 2(上) 和 i×2+1i\times 2+1(下),偶数情况把 xx 扔到目标栈上的时候采用的 pos2×i12\times i-1,因为最后一定会变为 2×i2\times i
CPP
#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define _rep(i,a,b) for(int i=(a);i>=(b);i--)
#define subset(i,x) for(int i=x;i;i=(i-1)&x)
#define pi pair<int,int>
#define arr(a) array<int,(a)>
#define RE return puts("0"),void()
#define cases(_) while((_)--) solve()
#define F fflush(stdout)
using namespace std;
const int mod=998244353;
inline void add(int& x,int y){x=(x%mod+y%mod+mod)%mod;}
inline void mul(int& x,int y){x=(x%mod)*(y%mod)%mod;}
inline void ckmin(int& x,int y){x=min(x,y);}
inline void ckmax(int& x,int y){x=max(x,y);}
const int N=1005,M=5000005;
int _=1,n,m,k,a[M];
int emp,cur,pos[N];
//pos=0: not in any stack, pos>=2: stack floor(pos/2)
deque<int> q[N];
vector<arr(3)> ans;
set<int> s;
// stack that allow join new element
inline void operate(int op,int s1,int s2){
	ans.push_back({op,s1,s2});
	if(op&1){
		if(!q[s1].empty() && q[s1].front()==s2) q[s1].pop_front();
		else q[s1].push_front(s2);
	}else{
		// assert(q[s1].size()),assert(q[s2].size()),assert(q[s1].back()==q[s2].back());
		if(q[s1].empty() || q[s2].empty()) exit(0);
		if(q[s1].back()==q[s2].back()){
			q[s1].pop_back(),q[s2].pop_back();
			for(int t:q[s1]) pos[t]++;
			for(int t:q[s2]) pos[t]++;
		}
	}
}
inline void upd(int x){
	// printf("!!! %d %d %d %d\n",x,pos[x],cur,s.size());
	if(!pos[x] && cur<2*n-2){
		int now=*s.begin();
		cur++,pos[x]=(now<<1|1)-q[now].size();
		operate(1,now,x);
		if(q[now].size()==2 && s.count(now)) s.erase(now);
	}else if(!(pos[x]&1) || (pos[x]&1 && q[pos[x]>>1].size()==1)){
		int now=(pos[x]>>1),tmp=(int)q[now].size();
		operate(1,now,x),pos[x]=0,cur--;
		if(tmp>=2 && q[now].size()==1) s.insert(now);
	}else{
		int now=(pos[x]>>1),tmp=(int)q[now].size();
		operate(1,emp,x),operate(2,now,emp),pos[x]=0,cur--;
		if(tmp>=2 && q[now].size()==1) s.insert(now);
	}
}
void solve(){
	scanf("%d%d%d",&n,&m,&k),emp=n,s.clear(),cur=0,ans.clear();
	rep(i,1,m) scanf("%d",&a[i]);
	rep(i,1,n-1) s.insert(i); 
	rep(i,1,m){
		int x=a[i];
		// printf("-> %d %d %d %d\n",i,x,pos[x],cur);
		// for(int t:q[1]) printf("%d ",t);
		// puts("");
		if(!pos[x] && cur==2*n-2){
			int nxt=-1;
			rep(o,i+1,m){
				if(pos[a[o]] && a[o]==q[pos[a[o]]>>1].back()){nxt=o;break;}
				if(a[o]==x){nxt=o;break;}
			}
			// assert(nxt!=-1);
			// printf("%d\n",nxt);
			if(a[nxt]==x){
				rep(o,i,nxt){
					if(o==i || o==nxt) operate(1,emp,a[o]);
					else upd(a[o]);
				}
			}else{
				int now=(pos[a[nxt]]>>1);
				int t=q[now].front(),cnt=0,tmp;
				rep(o,i+1,nxt) cnt+=(a[o]==t);
				if(cnt&1){
					// puts("Q");
					operate(1,emp,x),pos[x]=(emp<<1|1),cur++; 
					rep(o,i+1,nxt) upd(a[o]);
					if(s.count(now)) s.erase(now);
					s.insert(emp),emp=now;
				}else{
					operate(1,now,x),pos[x]=(now<<1)-1;
					rep(o,i+1,nxt-1){
						// printf("! %d\n",pos[a[o]]);
						if(a[o]==t) upd(a[o]),pos[a[o]]=(now<<1),cur++;
						else upd(a[o]);
					}
					operate(1,emp,a[nxt]),pos[a[nxt]]=0,operate(2,now,emp);
				}
			}
			i=nxt;
		}else upd(x);
	}
	// assert(cur==0);
	printf("%d\n",(int)ans.size());
	for(arr(3) t:ans){
		if(t[0]&1) printf("%d %d\n",t[0],t[1]);
		else printf("%d %d %d\n",t[0],t[1],t[2]);
	}
	rep(i,1,n) while(!q[i].empty()) q[i].pop_front();
	rep(i,1,m) a[i]=0;
	rep(i,1,k) pos[i]=0;
}
signed main(){
	scanf("%d",&_);
	cases(_);
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...