1. 程式人生 > 其它 >CSP-S 2021 T3 迴文通過記錄

CSP-S 2021 T3 迴文通過記錄

據說,T3比T1簡單,但是我花了一個下午……

做法

具體做法參見here
這裡只寫程式碼和deque的使用(按照人家思路打的,就不贅述了)。

#include<bits/stdc++.h>
using namespace std;
deque<int> c,d;//雙端佇列
int n,n2;//n2存2*n
int a[1000005];//一定要開2倍
char ans[1000005],now[1000005];
int fnd(int v,int l,int r){//在[l,r]區間內找到v
	for(int i=l;i<=r;i++) if(a[i]==v) return i;
	return -1;
}
void suan(){//計算
	int p=2;//從2開始
	while(1){
		if(c.empty()&&d.empty()) break;//已經完成
		else if(d.empty()){//d是空的,只能選c
			if(c.front()!=c.back()){now[1]='Z';return;}//沒有方法了,放棄
			now[p]=now[n2-p+1]='L';//都是L
			c.pop_front();c.pop_back();//去掉
		}
		else if(c.empty()){//c是空的
			if(d.front()!=d.back()){now[1]='Z';return;}//同上
			now[p]=now[n2-p+1]='R';
			d.pop_front();d.pop_back();
		}
		else{
			if(c.front()==c.back()&&c.size()>1){//自己對自己
				now[p]=now[n2-p+1]='L';//同上
				c.pop_front();c.pop_back();
			}
			else if(c.back()==d.front()){//c的下面對d上面
				now[p]='L';now[n2-p+1]='R';
				c.pop_back();d.pop_front();
			}
			else if(c.front()==d.back()){//c上對d下
				now[p]='R';now[n2-p+1]='L';
				c.pop_front();d.pop_back();
			}
			else if(d.front()==d.back()&&d.size()>1){//d的,同27~28
				now[p]=now[n2-p+1]='R';
				d.pop_front();d.pop_back();
			}
			else{now[1]='Z';return ;}//都不行
		}
		p++;//下一位
	}
}
bool lexicographical(){//字典序/xyx
	int i=1;
	while(i<=n2&&now[i]==ans[i]) i++;//只要一樣就往後看
	return i<=n2&&now[i]<ans[i];//下一位他更小
}
int main(){
	int t,he;
	cin>>t;
	while(t--){
		cin>>n;n2=2*n;
		ans[1]='Y';
		for(int i=1;i<=n2;i++) cin>>a[i];
		while(!c.empty()) c.pop_front();
		while(!d.empty()) d.pop_front();
		he=fnd(a[1],2,n2);
		for(int i=he-1;i>=2;i--) c.push_back(a[i]);
		for(int i=he+1;i<=n2;i++) d.push_back(a[i]);
		now[1]=now[n2]='L';
		suan();
		if(lexicographical())
			for(int i=1;i<=n2;i++)
				ans[i]=now[i];
		while(!c.empty()) c.pop_front();
		while(!d.empty()) d.pop_front();
		he=fnd(a[n2],1,n2-1);
		for(int i=he-1;i>=1;i--) c.push_back(a[i]);
		for(int i=he+1;i<=n2-1;i++) d.push_back(a[i]);
		now[1]='R';now[n2]='L';
		suan();
		if(lexicographical())
			for(int i=1;i<=n2;i++)
				ans[i]=now[i];
		if(ans[1]=='Y') cout<<-1;
		else for(int i=1;i<=n2;i++) cout<<ans[i];
		cout<<endl;
	}
	return 0;
}

這裡,push_back就是在尾端插入,push_front是在頭部。
pop_back和pop_front同理。
size和empty表示大小和是否為空。

如何被坑

最開始寫了一個類似的程式碼,只有40pts,原因是輸出的時候莫名其妙反過來了……
後來發現了xio問題,改正了,立刻獲得96pts。
然後就一直找問題,死活找不出來……
one hour later
發現ans和now應該開2倍,但是沒想到a/wul
a half hour later
才想起來a也要2倍/kx,洛谷就100了