220514西南科技正式赛补题

A:花非花

题目:

用Manacher,关于这个最长回文串所有解法可以参考这个连接:力扣https://leetcode.cn/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/

以前看过没练过所以用不来(寄

马拉车处理臂长数组以后,本题要求的是回文串个数,即对于每个i和它对应的p[i],都有 i-p[i]+1~i 部分为开头的回文串数量+1。这一步我暴力尝试了一次但是TLE。题解中提了一嘴差分处理区间加,嗯确实只能这样。

关于差分区间加减,可以参考这个连接:(本处用到的是最下面 3.用途 的第一个小点)

差分数组 快速处理区间加减操作_weixin_56336619的博客-CSDN博客_区间的加减法第一行n和m(都是100以内) 接下来n行 每行两个1-m的数 代表区间[l, r]输出没有被任何区间覆盖到的整数们(第一行输出个数)题目链接示例:每次输入区间[l,r]打标记——对数组下标[l,r]的值均执行+1操作for i in range(n): l,r=input().split() l,r=int(l),int(r) arr[l]+=1; arr[r+1]-=1; # 数组[l,r]区间+1若干次操作以后#若干次操作后数组的样子for .https://blog.csdn.net/weixin_56336619/article/details/115528331?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165267129316782395367748%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165267129316782395367748&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-115528331-null-null.142%5Ev9%5Epc_search_result_cache,157%5Ev4%5Econtrol&utm_term=%E5%B7%AE%E5%88%86%E5%A4%84%E7%90%86%E5%8C%BA%E9%97%B4%E5%8A%A0&spm=1018.2226.3001.4187AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
int a[N],b[N],p[N],cnt,n;
int c[N];
void init(){
	//创建马拉车数组 
    b[cnt]=-1;
    for(int i=1;i<=n;i++){
         b[++cnt]=a[i];
         b[++cnt]=-2;
    }
    b[++cnt]=-3;
}
void manacher(){
    int mx=0,id=0;
    for(int i=1;i<=cnt;i++){
    	//取值 
        if(i<mx)p[i]=min(mx-i,p[2*id-i]);
		else p[i]=1;
		//中心扩展 
        while(b[i-p[i]]==b[i+p[i]])p[i]++;
        if(i+p[i]>mx){
            mx=i+p[i];
            id=i;
        }
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    //用马拉车对数组进行预处理得到臂长数组p[]; 
    init();
    manacher();
    
//这种找最终答案的方法要超时!!注意循环嵌套了   
//    for(int i=1;i<=cnt;i++){
//	    //找到i的臂长以后对i-pi+1~i的部分回文串数目++; 
//    	int x=i+1-p[i];
//    	for(int j=x;j<=i;j++)c[j]++;
//	}
//	for(int i=1;i<=cnt;i++){
//		if(b[i]>0)cout<<c[i]<<" ";
//	}
//	cout<<endl;
    
    for(int i=1;i<=cnt;i++){
    	//差分处理区间加 
        int x=i+1-p[i];
        c[x]++;
        c[i+1]--;
    }
    int res=0;
    for(int i=1;i<=cnt;i++){
        res+=c[i];
        //b[i]<0的部分为马拉车占位符 
        if(b[i]>0) cout<<res<<" ";
    }
}

J:满城烟水月微茫,人倚兰舟唱

简单队列模拟,没时间...

 

#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n,m,num[maxn],x;//num表示每堆有几张 
queue<int> q[maxn];
int ans;
int simulate(int yu){
	while(yu>0){
		int ming=-1,hua=-1;
		int ming_i=-1;
		//抽牌 
		for(int i=0;i<n;i++){
			if(!q[i].empty()){
				if(hua==-1){
					hua=q[i].front();
					q[i].pop();
				}
			}
			if(!q[i].empty()){
				if(ming==-1){
					ming_i=i;
					ming=q[i].front();
					q[i].pop();
				}
			}
			if(ming!=-1&&hua!=-1)break;
		}
		//小明开始使坏
		while(ming<=hua&&ming_i<n){
			if(ming_i<n-1)q[ming_i+1].push(ming);
			else yu--;
			
			if(!q[ming_i].empty()){
				ming=q[ming_i].front();
				q[ming_i].pop();
			}
			else if(ming_i+1<n){
				ming_i++;
				ming=q[ming_i].front();
				q[ming_i].pop();
			}
			else break;
		}
		if(ming>hua)ans++;
		yu-=2;
	}
	return ans;
} 
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>num[i];
		for(int j=0;j<num[i];j++){
			cin>>x;
			q[i].push(x);
		} 
	}
	cout<<simulate(m)<<endl;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值