CSP2019题解
Posted treap
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSP2019题解相关的知识,希望对你有一定的参考价值。
J组:
T1:
没什么好说的。
code:
#include <bits/stdc++.h>
using namespace std;
string s;
int main(){
cin >> s ;
int ans=0;
for(int i=0; i<8; i++)
if(s[i]==‘1‘)
ans++;
cout<<ans;
}
T2:
啊我考场上sb了没用队列
开一个队列,如果是地铁直接累加答案
是公交就在优惠券的队列找,不断弹出队头
code:
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
int n ;
queue < long long > q [100005];
long long ans = 0 ;
int main(){
cin >> n ;
int k = 0 ;
int flag;
for(int i=1; i<=n; i++){
int opt , p , t ;
cin >> opt >> p >> t ;
if(opt == 0){
ans += p ;
q[p] . push (t) ;
k++ ;
}
else{
int minn = 1e9 + 7 ;
for(int i=p; i<= 1000; i++){
while(!q[i].empty()&&q[i].front()+45<t)
q[i].pop();
if(!q[i].empty()){
if(minn>q[i].front()){
flag=i;
minn=q[i].front();
}
}
}
if(minn>1e9)
ans+=p;
else
q[flag].pop();
}
}
cout << ans << endl ;
return 0 ;
}
T3:
啊我又sb了看出正解没写
T=2提示了完全背包的做法,而你如果观手察玩n=1的情况就会发现每天是独立的,所以只要一维(我考场上写的是正解,然而开了三维,两位没用,连小范围都能爆空间,最后只写了10分送分)
跑T-1次完全背包即可。
code:
#include <bits/stdc++.h>
using namespace std;
int t,n,m,dp[10005],pri[105][105],wl[105],vl[105];
int main () {
scanf("%d%d%d",&t,&n,&m);
for (int i=1; i<=t; i++) {
for (int j=1; j<=n; j++) {
scanf("%d",&pri[i][j]);
}
if (i>=2) {
memset(dp,0,sizeof(dp));
for (int j=1; j<=n; j++) {
wl[j]=pri[i-1][j],vl[j]=pri[i][j]-pri[i-1][j];
for (int k=wl[j]; k<=m; k++) {
dp[k]=max(dp[k],dp[k-wl[j]]+vl[j]);
}
}
int tmp=0;
for (int j=1; j<=m; j++) {
tmp=max(tmp,dp[j]+m);
}
m=tmp;
}
}
printf("%d
",m);
return 0;
}
T4:
占坑...
顺便说一句T3T4都是原题,P2938,P3556 。
S组
Day1:
T1:
07年TG初赛原题
生成公式G(n) = B(n)^B(n+1)
code:
#include <iostream>
using namespace std;
unsigned long long n , k ;
int main(){
cin >> n >> k ;
k ^= k >> 1 ;
while(n--)
cout << (k>>n&1);
return 0 ;
}
T2:
重点讲解:
其实这题用到了kmp的思想
记l为失配数组,即当前节点上一个未被匹配的左括号
cnt是单个节点产生的贡献
ans为节点到根的贡献值和
先考虑链上做法
对于i ,继承l[i]=l[i-1],cnt[i]=cnt[i-1]
如果它是左括号,由于后面的情况未知,l[i] = i ;
如果它是右括号:
前面没有失配的括号,那它不产生任何贡献,跳过
否则 ,匹配两个括号, 让失配数组跳回失配位置-1所对应的的失配位置 , 该点产生的贡献即为其失配位置-1的贡献+1(这两个匹配括号又产生1个贡献)
累加ans
code:
for(int i=1; i<=n; i++) {
l[i] = l[ i - 1 ] , ans[i] = ans[ i - 1 ] ;
if(s[i]==‘(‘)
l[i] = i ;
else {
if( s[i] == ‘)‘ && l[i] ) {
cnt[i] = cnt[ l[i] -1 ] + 1 ;
l[i] = l[ l[i] - 1 ] ;
ans[i] += cnt[i] ;
}
}
......
}
注:代码是写blog时临时写的,可能有误,请谨慎食用
这个做法有什么好处:
1:容易理解
2:码量小(大部分都写的dfs)
3:便于扩展
树上做法:
只需将继承,转移时的i-1替换成father[i]
完整代码:
#include <iostream>
#include <cstdio>
using namespace std;
#define ll long long
ll n , f[500005] , ans[500005] , sum ;
ll l[500005] , cnt[500005] ;
char s[500005] ;
int main() {
cin >> n ;
cin >> s + 1 ;
for(int i=2; i<=n; i++)
cin >> f[i] ;
for(int i=1; i<=n; i++) {
l[i] = l[ f[i] ] , ans[i] = ans[ f[i] ] ;
if(s[i]==‘(‘)
l[i] = i ;
else {
if( s[i] == ‘)‘ && l[i] ) {
cnt[i] = cnt[ f[ l[i] ] ] + 1 ;
l[i] = l[ f[ l[i] ] ] ;
ans[i] += cnt[i] ;
}
}
sum ^= ( ans[i] ) * ( ll ) ( i ) ;
}
cout << sum << endl ;
}
本题总结:
本题作为T2,做法显然,思路清晰,码量适中,是一道不可多得的签到题
独立完成此题,可以加深链上问题扩展到树上一类问题的理解,想出优秀简短的做法以吊打std
T3:
不会
Day2:
T1:
以上是关于CSP2019题解的主要内容,如果未能解决你的问题,请参考以下文章