すのはら荘春原庄的雪

Codeforces Round #806 (Div. 4)

Toretto·2022-07-13 22:11·56 次阅读

Codeforces Round #806 (Div. 4)

A. 略

B.语法题

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<set>
#include<cmath>
using namespace std;

#define int long long
const int maxn=2e5+5;

void solve() {
	string s;
	int n;cin>>n;
	cin>>s;
	map<char,int>mp;
	int ans=0;
	for(int i=0;i<n;i++) {
		if(!mp[s[i]]) {
			mp[s[i]]=1;
			ans+=2;
		}else ans++;
	}
	cout<<ans<<'\n';
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C.语法题

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<set>
#include<cmath>
using namespace std;

#define int long long
const int maxn=110;
int n,fin[maxn],ans[maxn];

void solve() {
	cin>>n;
    for(int i=1;i<=n;i++) cin>>fin[i];
    for(int i=1;i<=n;i++) {
        int op,cnt=0;
        cin>>op;
        string s;cin>>s;
        for(int i=0;i<s.size();i++) {
            if(s[i]=='U') cnt--;
            else cnt++;
        }
        cnt%=10;
        if(cnt>=0) ans[i]=(fin[i]+cnt)%10;
        else {
            ans[i]=(fin[i]+cnt+10)%10;
        }
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
        cout<<'\n';
}   

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int t;
	t=1;
	cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

D,这一题我用的map存字符串暴力判断,大佬们用的数学加思维什么的,本菜鸡属实不会,贴一下暴力的代码算了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<set>
#include<cmath>
using namespace std;

#define int long long
const int maxn=1e5+5;
int n;
string s[maxn];
int ans[maxn];

void solve() {
	cin>>n;
	map<string,int>mp;
	for(int i=1;i<=n;i++) {
		cin>>s[i];
		mp[s[i]]=1;
	}
	for(int i=1;i<=n;i++) {
        ans[i]=0;
		string op;
		for(int j=0;j<s[i].size();j++) {
			op+=s[i][j];
			string ok;
			for(int k=j+1;k<s[i].size();k++) ok+=s[i][k];
			if(mp[op]&&mp[ok])  {
				ans[i]=1;
				break;
			}
		}
	}
	for(int i=1;i<=n;i++) cout<<ans[i];
	cout<<'\n';
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int t=1;
	cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

E.这一题很怪,一开始推了一个求原矩阵旋转3次每次1的数量的公式,但是很奇怪的wa了(就是太菜了罢了),便直接开数组存每次旋转的状态,也十分的暴力。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<set>
#include<cmath>
using namespace std;

#define int long long
const int maxn=110;
char s[maxn][maxn],p[maxn][maxn];
int ans[maxn][maxn];
int n;

void solve() {
	cin>>n;
    int h=3,m=n/2;
    memset(ans,0,sizeof ans);
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            cin>>s[i][j];
            if(s[i][j]=='1') ans[i][j]++;
        }
    }
    while(h--) {
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                p[i][j]=s[n-j+1][i];
                    if(p[i][j]=='1') ans[i][j]++;
            }
        }
        for(int i=1;i<=n;i++) {
            for(int j=1;j<=n;j++) {
                s[i][j]=p[i][j];
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=m;i++) {
        for(int j=1;j<=m;j++) {
            cnt+=min(ans[i][j],4-ans[i][j]);
        }
    }
    if(n&1) {
        for(int i=1;i<=m;i++) {
            cnt+=min(ans[m+1][i],4-ans[m+1][i]);
        }
    }
    cout<<cnt<<'\n';
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int t;
	t=1;
	cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

F.猛一看f题,我的思路便是线段树存区间最小值,以ai<i的所有数据建树,依次求i+1到最后的区间中大于i的个数。但是仔细一想根本不必如此麻烦,f题考查的仅仅是一个简单前缀和问题。

我们用一个数组b来存表示前i项满足ai小于i的数量,对于每一个ai,前边便有b[a[i]-1]个数与之匹配,加起来即可

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<set>
using namespace std;

#define int long long
const int maxn=2e5+5;
int b[maxn];

void solve() {
    int n;
    cin>>n;
    int ans=0;
    for(int i=1,x;i<=n;i++) {
        cin>>x;
        b[i]=b[i-1];
        if(x<i) b[i]++;
        if(x<i&&x-1>0) {
            ans+=b[x-1];
        }
    }
    cout<<ans<<'\n';
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--) {
        solve();
    }
    return 0;
}

G.dp,

逐步分析:

1.状态表示

  f[i][j]表示第i项用了j次坏钥匙的价值。这样表示的好处是j=0时可以表示用好钥匙的价值。

2.转移方程:

  当j=0非常好处理,因为j=0,所以前边所有的箱子均使用的好钥匙,直接加起来即可。

    即 f[i][0]=f[i-1][0]+a[i]-k; (k是好钥匙的价格)

  难点就在j!=0时,这时候我们可以枚举j,之前便使用了j-1次坏钥匙或j次,分别枚举取最大值即可

      

这里的ans数组表示的是第i个箱子衰退j次后剩余的价值。

最后我们枚举第n位使用了j次坏钥匙取最大值即可,但值得注意的是,如果n大于31,那么使用了31次钥匙后之后所有的箱子剩余价值必定为0,这时坏钥匙与好钥匙的价值均为0,即默认使用坏钥匙,但是可能会i<31的时候有的箱子使用了好钥匙,而i>=31 的时候使用的坏钥匙,这时候在两者之间可能会有价值过大的箱子使用好钥匙的价值比坏钥匙大,而转移的时候我们默认i>=31均为0,会使结果降低,因此需要特判一下。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#include<set>
#include<cmath>
using namespace std;

#define int long long
const int maxn=2e5+5;
int n,k,a[maxn],f[maxn][40],ans[maxn][40];

void solve() {
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=0;i<=n;i++) {
		for(int j=0;j<=31;j++) {
			f[i][j]=ans[i][j]=0;
		}
	}
	for(int i=1;i<=n;i++) {
		int op=a[i],cnt=0;
		while(op) {
			ans[i][++cnt]=op/2;
			op/=2;  
		}
	}
	f[1][0]=a[1]-k;
	f[1][1]=a[1]/2;
	for(int i=2;i<=n;i++) {
		f[i][0]=f[i-1][0]+a[i]-k;
		for(int j=1;j<=min((int)31,i);j++) {
			f[i][j]=f[i-1][j]+ans[i][j]-k;
		}
		for(int j=1;j<=min((int)31,i);j++) {
			f[i][j]=max(f[i][j],f[i-1][j-1]+ans[i][j]);
		}
	}
	int op=-1e9-7;
	for(int i=0;i<=31;i++) op=max(op,f[n][i]);
	for(int i=n;i>=31;i--) op=max(op,f[i][31]);
	cout<<op<<'\n';
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	int t;
	cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

                                                                           

posted @   cbmango  阅读(56)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示