[題解]AtCoder Beginner Contest 380(ABC380) A~F

Sinktank發表於2024-11-17

A - 123233

照題意統計即可。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
string s;
map<char,int> ma;
signed main(){
	cin>>s;
	for(char i:s) ma[i]++;
	if(ma['1']==1&&ma['2']==2&&ma['3']==3) cout<<"Yes\n";
	else cout<<"No\n";
	return 0;
}

B - Hurdle Parsing

還是照題意模擬即可。

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
string s;
signed main(){
	cin>>s;
	int cnt=0;
	for(int i:s){
		if(i=='|'){
			if(cnt) cout<<cnt<<" ";
			cnt=0;
		}else if(i=='-') cnt++;
	}
	return 0;
}

C - Move Segment

就是將第\(k\)1的連通塊移到緊貼第\(k-1\)1的連通塊後面。

照題意模擬即可(程式碼過於不可讀,不建議參考)。

點選檢視程式碼
#include<bits/stdc++.h>
#define N 500010
using namespace std;
int n,k;
string s,t;
int ll[N],rr[N],idx;
int p[N];
signed main(){
	cin>>n>>k>>s;
	s=' '+s+' ';
	int l,r;
	for(int i=1;i<=n;i++){
		if(s[i]!=s[i-1]&&s[i]=='1') l=i;
		if(s[i]!=s[i+1]&&s[i]=='1'){
			r=i;
			ll[++idx]=l,rr[idx]=r;
		}
	}
	int cha=ll[k]-rr[k-1];
	ll[k]=ll[k]-cha+1;
	rr[k]=rr[k]-cha+1;
	for(int i=1;i<=idx;i++){
		p[ll[i]]++,p[rr[i]+1]--;
	}
	for(int i=1;i<=n;i++){
		p[i]+=p[i-1];
		cout<<p[i];
	}
	return 0;
}

D - Strange Mirroring

將字串\(s\)反轉得到\(s'\),拼接起來是\(s\ s'\ s'\ s\ \dots\)。將每個串依次編號為\(0,1,2,3,\dots\),透過手玩可以發現第\(x\)個串為\(s\),當且僅當\(\text{popcount}(x)=0\),其中\(\text{popcount}(x)\)是指\(x\)的二進位制中\(1\)出現的次數。

還是直接模擬就可以。

點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
#define Q 200010
using namespace std;
string s;
int q,k,n;
char ch(char a){
	if(a>='A'&&a<='Z') return a-'A'+'a';
	return a-'a'+'A';
}
signed main(){
	cin>>s>>q;
	n=s.size();
	for(int i=1;i<=q;i++){
		cin>>k;
		k--;
		int round=k/n;
		k%=n;
		if(__builtin_popcountll(round)&1) cout<<ch(s[k]);//changed
		else cout<<s[k];
		cout<<" ";
	}
	return 0;
}

E - 1D Bucket Tool

當時在機房所以沒裝外掛,用的百度翻譯,然後就理解錯題意了,以為操作\(2\)要求輸出\(x\)所在位置的顏色出現了多少次,然後……寄了( ̄  ̄|||)

map來維護顏色相同的區間。

對於詢問\(1\),用lower_bound()找到該元素在set中的哪個區間,然後將該區間刪掉,再新增進去修改過顏色的區間即可。

注意如果相鄰的區間顏色和該區間修改後的顏色相同,需要把相鄰的區間也刪掉,合併進新新增的區間。為了防止一系列邊界問題,我們在頭尾各加\(2\)個哨兵,顏色設為\(-1\)即可。

點選檢視程式碼
#include<bits/stdc++.h>
#define N 500010
#define Q 200010
using namespace std;
struct Range{int l,r,color;};
class cmpclass{
public:
	bool operator()(const Range& a,const Range& b) const{
		return a.r<b.r;//按右端點從小到大
	}
};
set<Range,cmpclass> se;
int n,q,cnt[N];
signed main(){
	cin>>n>>q;
	se.insert({0,0,-1});
	se.insert({n+1,n+1,-1});
	for(int i=1;i<=n;i++) se.insert({i,i,i}),cnt[i]=1;
	while(q--){
		int op,x,c;
		cin>>op;
		if(op==1){
			cin>>x>>c;
			auto it=se.lower_bound({x,x,x});
			int l=it->l,r=it->r,color=it->color;
			cnt[c]+=(r-l+1);
			cnt[color]-=(r-l+1);
			it=se.erase(it);
			if(it->color==c){
				r=it->r;
				it=se.erase(it);
			}
			it--;
			if(it->color==c){
				l=it->l;
				it=se.erase(it);
			}
			se.insert({l,r,c});
		}else{
			cin>>x;
			cout<<cnt[x]<<"\n";
		}
	}
	return 0;
}

F - Exchange Game

注意到\(n+m+k\)一共才\(12\),果斷壓位暴搜。

具體來說,用一個\(3\)進位制數來表示每一張牌的狀態,\(0\)表示在Takahashi手裡,\(1\)表示在Aoki手裡,\(2\)表示在桌上。

搜尋時提供該三進位制數,還有當前的操作者(\(0\)Takahashi)。先列舉取出哪張牌,再列舉拿回哪張牌(注意也可以不拿)。

如果當前狀態能到達的所有狀態中,存在勝者為自己的狀態,則說明此狀態下,自己必勝;否則(即所有狀態都是對方獲勝),此狀態下自己必輸。根節點的狀態就是最終答案。

注意要記憶化。

點選檢視程式碼
#include<bits/stdc++.h>
#define N 13
#define int long long
using namespace std;
int n,m,l,nn,a[N],pow3[N],f[2][531441];//3^11=531441
struct Status{
	int v=0;
	int get(int pos){return v/pow3[pos]%3;}
	Status chp(int pos,int vv){return {v+(vv-get(pos))*pow3[pos]};}
};
bool dfs(bool cur,Status sta){
	if(f[cur][sta.v]!=-1) return f[cur][sta.v];
	for(int i=0;i<nn;i++){//打出的牌
		if(sta.get(i)!=cur) continue;
		for(int j=0;j<nn;j++){//取回的牌
			if(sta.get(j)!=2||a[j]>=a[i]) continue;
			if(dfs(cur^1,sta.chp(i,2).chp(j,cur))==cur) return (f[cur][sta.v]=cur);
		}
		if(dfs(cur^1,sta.chp(i,2))==cur) return (f[cur][sta.v]=cur);
	}
	return (f[cur][sta.v]=cur^1);
}
signed main(){
	memset(f,-1,sizeof f);
	pow3[0]=1;
	for(int i=1;i<N;i++) pow3[i]=pow3[i-1]*3;
	cin>>n>>m>>l;
	nn=n+m+l;
	for(int i=0;i<nn;i++) cin>>a[i];
	Status sta;
	for(int i=0;i<nn;i++) sta=sta.chp(i,(i>=n)+(i>=n+m));
	cout<<(dfs(0,sta)?"Aoki\n":"Takahashi\n");
	return 0;
}

相關文章