首页 > 其他分享 >CSP-S 2021

CSP-S 2021

时间:2023-06-07 21:11:24浏览次数:50  
标签:... ch 括号 2021 序列 廊桥 CSP dp

P7913 [CSP-S 2021] 廊桥分配

让我们先忽略廊桥数量的限制来安排航班。我们维护一个空闲的廊桥队列,每到达一架航班,就给它安排编号最小的廊桥供其使用。

现在加上廊桥数量的限制。容易发现刚才的廊桥分配方法直接就帮我们解决了廊桥限制的问题:如果当前有 \(n\) 个廊桥可供使用,则分配到 \(n+1\) 号及以后的廊桥实质上就是分配到远机位了,不需要再做任何额外的处理。

到这里做法就很清晰了:我们按照开头提到的分配方法来安排航班的停靠位置,记录各廊桥停靠的航班数,做一个前缀和,最后枚举分配给某个区的廊桥数,算出各情况下两区实际使用廊桥的航班数总和,即可解决本题。

第一篇题解写的挺好的,自己就不打了,嘿嘿。

\(code\)

#include<bits/stdc++.h>
#define N 100005
#define X first
#define Y second
#define pii pair<int,int>  
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
struct node{
	int l,r;
	bool operator < (const node& A) const{return l==A.l?r<A.r:l<A.l;}
}a[N],b[N];
int n,m1,m2,ans;
int res1[N],res2[N];
void solve(node* t,int m,int* res){
	priority_queue<pii,vector<pii>,greater<pii> > lq;
	priority_queue<int,vector<int>,greater<int> > wq;
	for(int i=1;i<=n;++i) wq.push(i);
	for(int i=1;i<=m;++i){
		while(!lq.empty()&&t[i].l>=lq.top().X){
			wq.push(lq.top().Y);lq.pop();
		}
		if(wq.empty()) continue;
		int x=wq.top();
		wq.pop(),res[x]++;
		lq.push(make_pair(t[i].r,x));
	}
	for(int i=1;i<=n;++i) res[i]+=res[i-1];
}
int main(){
	n=read(),m1=read(),m2=read();
	for(int i=1;i<=m1;++i) a[i].l=read(),a[i].r=read();
	for(int i=1;i<=m2;++i) b[i].l=read(),b[i].r=read();
	sort(a+1,a+1+m1),sort(b+1,b+1+m2);
	solve(a,m1,res1),solve(b,m2,res2);
	for(int i=0;i<=n;++i) ans=max(res1[i]+res2[n-i],ans);
	printf("%d\n",ans);
	return 0;
}

P7914 [CSP-S 2021] 括号序列 :

首先肯定是区间dp,令 \(dp_{i,j}\) 表示从位置 \(i\) 到位置 \(j\) 一共的合法序列总情况数量。

但是不同的形态可能会有不同的转移,如:(S)这种只能从S转移过来等等。所以只开两维的dp状态必然是不够的。

可以将两位的dp扩充为三维,第三位表示不同的形态种类,dp状态就变成了 \(dp_{i,j,[0,5]}\)。没种状态表示:

  • \(dp_{i,j,0}\): 形态如 ***...* 的括号序列(即全部是*)。

  • \(dp_{i,j,1}\): 形态如 (...)的括号序列(即左右直接被括号包裹且最左边括号与最右边的括号相互匹配)。

  • \(dp_{i,j,2}\): 形态如 (...)**(...)*** 的括号序列(即左边以括号序列开头,右边以*结尾)。

  • \(dp_{i,j,3}\): 形态如 (...)***(...)*(...) 的括号序列(即左边以括号序列开头,右边以括号序列结尾,注意:第2种形态也属于这种形态)。

  • \(dp_{i,j,4}\): 形态如 ***(...)**(...) 的括号序列(即左边以*开头,右边以括号序列结尾)。

  • \(dp_{i,j,5}\): 形态如 ***(...)**(...)** 的括号序列(即左边以*开头,右边以*结尾,注意:第1种形态也属于这种形态)。

设定完状态以后,转移就直接出来了,注意:为了防止连续超过 \(k\) 个*一起出现,转移的时候不能把两段*拼接起来,在状态1的时候暴力判断一下两端的距离是否是 \(\le k\) 的,是的才能转移。

  • \(dp_{l,r,0}\)(直接特判)
    没什么好解释的

  • $dp_{l,r,1}=(dp_{l+1,r-1,0}+dp_{l+1,r-1,2}+dp_{l+1,r-1,3}+dp_{l+1,r-1,4})\times compare(l,r) $,
    $compare(i,j) $ 表示第 \(i\) 位与第 \(j\) 位能否配对成括号,能则为 \(1\),否则为 \(0\)。
    加括号时,里面可以是全*,可以是有一边是 * , 也可以是两边都不是 * ,唯独不能两边都是 * 且中间有括号序列。

  • \(dp_{l,r,2}=\sum\limits_{i=l}^{r-1} dp_{l,i,3}\times dp_{i+1,r,0}\)
    左边以括号序列开头且以括号序列结尾的是第3种,右边接一串*,是第0种。

  • \(dp_{l,r,3}=\sum\limits_{i=l}^{r-1} (dp_{l,i,2}+dp_{l,i,3})\times dp_{i+1,r,1}+dp_{l,r,1}\)
    左边以括号序列开头,结尾随便,符合的有第2和第3种,右边接一个括号序列,是第1种。
    记得加上直接一个括号序列的。

  • \(dp_{l,r,4}=\sum\limits_{i=l}^{r-1} (dp_{l,i,4}+dp_{l,i,5})\times dp_{i+1,r,1}\)
    左边以 * 开头,结尾随便,符合的有第4和第5种,右边接一个括号序列,是第1种。

  • \(dp_{l,r,4}\) 还有一种递推式也是可以的 , \(dp_{l,r,4}=\sum\limits_{i=l}^{r-1} (dp_{l,i,0}\times dp_{i+1,r,3})\)(亲测有效,可见两次提交记录 link1link2)

  • \(dp_{l,r,5}=\sum\limits_{i=l}^{r-1} dp_{l,i,4}\times dp_{i+1,r,0}+dp_{l,r,0}\)
    左边以* 开头,以括号序列结尾,符合的是第4种,右边接一串*,是第0种。
    记得加上全是 * 的。

最后,答案必须以括号序列开头,以括号序列结尾,所以直接是 \(dp_{1,n,3}\)。

这样,初始状态也就没什么问题了,对于所有的 \(i\) 满足 \(1\le i \le n\),有 \(dp_{i,i-1,0}=1\) 。

最终时间复杂度 \(O(6\times n^3)\) 不到,(后半部分填不满 \(n^3\) )。

记得开long long,并且取模。

$code $

#include<bits/stdc++.h>
#define N 505
#define mod 1000000007
#define int long long
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,k;
char s[N];
int f[N][N][6]; 
// f 0 *** 
// f 1 ()
// f 2 ()***  
// f 3 ()**()  包含 f 1 
// f 4 ***()**()
// f 5 ***()**()***  包含 f 0 
bool check(int a,int b){return (s[a]=='('||s[a]=='?')&&(s[b]==')'||s[b]=='?');}
signed main(){
	n=read(),k=read();
	scanf("%s",s+1);
	for(int i=1;i<=n;++i) f[i][i-1][0]=1;
	for(int l=1;l<=n;++l){
		for(int i=1;i+l-1<=n;++i){
			int j=i+l-1;
			if(l<=k) f[i][j][0]=f[i][j-1][0]&&(s[j]=='?'||s[j]=='*');
			if(l>=2){
				if(check(i,j)) f[i][j][1]=(f[i+1][j-1][0]+f[i+1][j-1][2]+f[i+1][j-1][3]+f[i+1][j-1][4])%mod; 
				for(int k=i;k<j;++k){
					f[i][j][2]=(f[i][j][2]+f[i][k][3]*f[k+1][j][0])%mod;
					f[i][j][3]=(f[i][j][3]+(f[i][k][2]+f[i][k][3])*f[k+1][j][1])%mod; 
				//	f[i][j][4]=(f[i][j][4]+(f[i][k][4]+f[i][k][5])*f[k+1][j][1])%mod;  //两种均可 
					f[i][j][4]=(f[i][j][4]+f[i][k][0]*f[k+1][j][3])%mod;
					f[i][j][5]=(f[i][j][5]+f[i][k][4]*f[k+1][j][0])%mod;
				}
			}
			f[i][j][5]=(f[i][j][5]+f[i][j][0])%mod;
			f[i][j][3]=(f[i][j][3]+f[i][j][1])%mod;
		}
	}
	printf("%lld\n",f[1][n][3]);
	return 0;
} 

P7915 [CSP-S 2021] 回文

枚举 \(b\) 中开头的值(显然它只能是 \(a\) 的开头和末位),然后在 \(a\) 中找到与之对应的值 (即 \(b\) 的末位),这就相当于一个区间往里面缩,一个区间往外拓展,这样搜索的复杂度是 \(O(2^{n/2})\)。

考虑对其再来一个贪心,显然优先级为 \(LL --> LR --> RL --> RR\),只要有一个可行我们就只搜这一条路,那么复杂度为 \(O(n)\) (每次只移动一次,每移动一次数组长度 \(-2\) )。

\(code\)

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int T,n;
char ans[N];
int a[N],b[N],L[N],R[N];
void init(){
	memset(b,0,sizeof(b));
	memset(ans,0,sizeof(ans));
	memset(L,0,sizeof(L));
	memset(R,0,sizeof(R));
}
bool solve(int lst,int Li,int Ri){
	if(Li==2) ans[1]='L';
	else ans[1]='R';
	int l=lst,r=lst,bg=2,ed=n-1;
	for(int i=1;i<n/2;++i){
		if(R[a[Li]]==l-1) l--,Li++,ans[bg++]='L',ans[ed--]='L';
		else if(R[a[Li]]==r+1) r++,Li++,ans[bg++]='L',ans[ed--]='R';
		else if(L[a[Ri]]==l-1) l--,Ri--,ans[bg++]='R',ans[ed--]='L';
		else if(L[a[Ri]]==r+1) r++,Ri--,ans[bg++]='R',ans[ed--]='R';
		else return 0;
	}
	ans[n]='L';
	for(int i=1;i<=n;++i) printf("%c",ans[i]);printf("\n");
	return 1;
}
signed main(){
	T=read();
	while(T--){
		init();
		n=read()*2;
		for(int i=1;i<=n;++i) a[i]=read(),L[a[i]]?R[a[i]]=i:L[a[i]]=i;
		if(solve(R[a[1]],2,n)) continue;
		if(solve(L[a[n]],1,n-1)) continue;
		printf("-1\n");
	}
	return 0;
} 

P7916 [CSP-S 2021] 交通规划

标签:...,ch,括号,2021,序列,廊桥,CSP,dp
From: https://www.cnblogs.com/jiangchen4122/p/17464587.html

相关文章

  • CSP-S 2020
    日期计算以\(400\)年为周期,每\(400\)年都有恰好\(146097\)天。(\(146097=365\times400+100-4+1\))预处理出\(400\)年内的情况,将年份模\(400\)即可快速得到答案。几个简化代码的技巧:对于格里高利历,以\(1200\)年\(1\)月\(1\)日为起始日,\(r\)减去跳过的天数(\(2159351\))。(\(21593......
  • 2021-05-18:金朝阳上课课堂
     ......
  • 2021-08-12--Web前端性能指标和性能优化(综述)
    title:网站的几个性能指标和优化(简易)categories:-网络安全与性能优化tags:-性能优化-性能指标-白屏时间-首屏时间-TTFBabbrlink:5c56date:2021-08-1223:42:49updated:2021-08-1223:42:49来源:https://m.sohu.com/a/201865334_509523/关于......
  • 2021-01-09--网络安全问题清单:问题类型-问题描述-解决方案
    title:网络安全问题清单:问题类型-问题描述-解决方案categories:-网络安全与性能优化tags:-网络安全-网站测试-安全清单abbrlink:'393'date:2021-01-0913:02:39updated:2021-01-0913:02:39最近收到一份网络安全检查清单(如下,有删减),再加上部分的IBM......
  • Apr 2021-Lucid Dreaming for Experience Replay: Refreshing Past States with the
    摘要:经验回放(ER)通过允许智能体在回放缓冲区中存储和重用其过去的经验,提高了离线强化学习(RL)算法的数据效率。虽然已经提出了许多技术,以通过偏差如何从缓冲区中采样来增强ER,但迄今为止,它们还没有考虑在缓冲区内刷新经验的策略。本文提出了用于经验回放的清醒梦(LiDER),一个概念上......
  • HTTP Content-Security-Policy CSP策略
       CSP(ContentSecurityPolicy)内容安全策略是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本(XSS)和数据注入攻击等。无论是数据盗取,网站内容污染还是恶意软件分发,这些攻击都是主要的手段。   CSP被设计完全向后兼容,不支持CSP的浏览器也能与实现了......
  • MISC|[GKCTF 2021]签到
    流量分析题追踪http流量,在tcp.streameq5处发现与flag相关字符从QER1=cat+%2Ff14g%7Cbase64这里可以看出数据是做了base64处理将返回的16进制数据转为字符,再进行base64解码得到以下字符wIDIgACIgACIgAyIK0wIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMyIjMiCNoQDjM......
  • 论文解读 | IROS 2021 | PTT:用于点云中3D单对象跟踪的点-轨道-变压器模块
    原创|文BFT机器人01背景在自动驾驶、机器人导航和增强现实等领域,3D单目标跟踪是一个重要的问题。传统的方法通常使用基于图像或激光雷达数据的2D或3D物体检测器来检测和跟踪目标。然而,这些方法通常需要大量的计算资源,并且对于复杂场景中的小目标或遮挡目标表现不佳。3D单目标跟......
  • 2021-2022年丘成桐女子中学生数学竞赛——笔试部分
    2021-2022年丘成桐女子中学生数学竞赛——笔试部分声明:本文为我从网上流传的试题写的个人解答,与清华大学求真书院官方无关。首届丘成桐女子中学生数学竞赛于2021年10月31日晚落下帷幕,共140名左右学生参加了笔试,35名学生入围面试,争夺“诺特奖”,最终决出金奖、银奖、铜......
  • Nginx:CVE-2021-23017;CVE-2022-41742
    nginx安全漏洞(CVE-2021-23017)详细描述Nginx是美国Nginx公司的一款轻量级Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。nginx存在安全漏洞,该漏洞源于一个离一错误在该漏洞允许远程攻击者可利用该漏洞在目标系统上执行任意代码。受影响版本0.6.18-1.20.0解决......