『模拟赛』暑假集训CSP提高模拟15

\[\color{red}{\huge 囍挂111pts} \]

叠词词恶心心

T1 串串

一眼马拉车。

我们来看看只翻转一次后就能得到答案的情况,就是如果某个位置的回文长度能到达这个字符串的末尾,那这个位置肯定能做翻转位置的,但是这种情况出现的位置只能在后半部分。

如果是翻转多次的话,那么位置只能出现在前半部分,我们只要保证在左半部分的位置的回文串长度左边能到达字符串的开头,并且右边的位置能满足翻转条件,那么这个位置也是答案。

可以套Manacher模板快速判断字符串中某个位置的长度。

但是,临提交前手欠加了register,比赛结束一看 大大的 \(\color{purple}{\huge RE}\) ,把 register 删了 大大的 \(\color{green}{\huge AC}\)。我真的服了,难道我是什么\(\color{red} \huge 先天RE圣体\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rd read()
#define mkp make_pair
#define psb push_back
#define re register
#define Elaina 0
#define random(a,b) (1ll*rand()*rand()*rand()%((b)-(a)+1)+(a))
inline int read(){
	int f=1,x=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) f=(ch=='-'?-1:1);
	for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
	return f*x;
}
const int p=1e9+7;
const int N=1e6+100;
const int inf=0x7fffffff7fffffff;

int T;
char s[N],str[N];
int vis[N],a[N];

void manacher(char s[]){
	int len=strlen(s),l=-1;
	str[++l]='$';
	str[++l]='#';
    for(int i=0;i<len;++i){
        str[++l]=s[i];
        str[++l]='#';
    }
    str[++l]=0;
	int mx=0,pos=0;
	for(int i=0;i<l;++i){
		a[i]=mx>i?min(a[2*pos-i],mx-i):1;
		while(str[i+a[i]]==str[i-a[i]]){
			++a[i];
		}
		if(i+a[i]>mx){
			mx=i+a[i];
			pos=i;
		}
	}
}

signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	
	cin>>T;
	while(T--){
		cin>>s;
		int len=strlen(s);
		
		manacher(s);
		
		int tmp=0;
		for(int i=2*len-2;i>=2;i-=2){
			vis[i/2]=0;
			tmp=(a[i]-1+i)/2;
			if(tmp==len) vis[i/2]=1;
			if(vis[tmp] && a[i]==i) vis[i/2]=1;
		}
        for(int i=1;i<len;++i){
        	if(vis[i]) 
        		cout<<i<<' ';
		}
		cout<<len<<'\n';
	}
	
	return Elaina;
}

T2 排排

结论题,不难想。

但挂了 11pts ?

不太理解,有没有dalao帮我看看(有疑问的地方已在代码中标出)?

我是唐氏。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rd read()
#define mkp make_pair
#define psb push_back
#define Elaina 0
#define random(a,b) (1ll*rand()*rand()*rand()%((b)-(a)+1)+(a))
inline int read(){
	int f=1,x=0;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) f=(ch=='-'?-1:1);
	for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
	return f*x;
}
const int p=1e9+7;
const int N=1e6+100;
const int inf=0x7fffffff7fffffff;

int T,n,a[N];

struct SZSZ{
	int num[N];
	
	int lowbit(int x){
		return x&(-x);
	}
	
	void add(int x,int k){
		while(x<=n){
			num[x]+=k;
			x+=lowbit(x);
		}
	}
	
	int query(int x){
		int sum=0;
		while(x>0){
			sum+=num[x];
			x-=lowbit(x);
		}
		return sum;
	}
}sz;

bool check(int x){
	int num=a[x];
	for(int i=1;i<=n;i++){
		if(i<x&&a[i]>num){
			return 0;
		}else if(i>x&&a[i]<num){
			return 0;
		}
	}
	return 1;
}

signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	
	cin>>T;
	while(T--){
		bool flag=0,is_pm=1;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			if(a[i]!=i){
				is_pm=0;
			}
		}
		if(is_pm){
			cout<<0<<'\n';
			continue;
		}
		if(a[1]==1){
			cout<<1<<'\n';
			continue;
		}
		if(a[n]==n){
			cout<<1<<'\n';
			continue;
		}
		if(a[1]==n && a[n]==1){
			cout<<3<<'\n';
			continue;
		}
		if(a[n]==1){
			cout<<2<<'\n';
			continue;
		}
		if(a[1]==n){
			cout<<2<<'\n';
			continue;
		}
		
		for(int i=1;i<=n;i++){
			if(a[i]==i&&sz.query(i-1)==i-1){
				flag=1;
                //break; 
			}
			sz.add(a[i],1);
		}
		
		for(int i=1;i<=n;i++) sz.add(a[i],-1);
		
		if(flag){
			cout<<1<<'\n';
			continue;
		}
		cout<<2<<'\n';
	}
	return Elaina;
}

T3 序序

T4 桥桥

原题P5443

posted @ 2024-08-07 15:11  Elaina_0  阅读(25)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end