Educational Codeforces Round 188 (Rated for Div. 2)
A. Passing the Ball
纯模拟的,但好像是找第一个 L 的位置就行
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n;
cin>>n;
string s;
cin>>s;
s=" "+s;
vector<int> st(n+1);
int now=1;
st[1]=1;
for(int i=2;i<=n;i++){
if(s[now]=='R'){
now++;
st[now]=1;
}
else{
now--;
st[now]=1;
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(st[i]) ans++;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
}
B. Right Maximum
直接 ST 表草过去了,火箭毛毛虫
实际好像是找所有前缀最大值的位置就行(?
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
struct ST {
int n;
vector<int> in1, in2, lg;
vector<vector<int>> Max, Min;
ST(int n) : n(n), in1(n + 1), in2(n + 1), lg(n + 1) {
for (int i = 2; i <= n; i++) {
lg[i] = lg[i / 2] + 1;
}
Max.resize(n + 1, vector<int>(lg[n] + 1));
Min.resize(n + 1, vector<int>(lg[n] + 1));
}
void init() {
for (int i = 1; i <= n; i++) {
Max[i][0] = in1[i];
Min[i][0] = in2[i];
}
int k = lg[n];
for (int j = 1; j <= k; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
Max[i][j] = max(Max[i][j - 1], Max[i + (1 << (j - 1))][j - 1]);
Min[i][j] = min(Min[i][j - 1], Min[i + (1 << (j - 1))][j - 1]);
}
}
}
int getMax(int l, int r) {
if (l > r) {
swap(l, r);
}
int k = lg[r - l + 1];
return max(Max[l][k], Max[r - (1 << k) + 1][k]);
}
int getMin(int l, int r) {
if (l > r) {
swap(l, r);
}
int k = lg[r - l + 1];
return min(Min[l][k], Min[r - (1 << k) + 1][k]);
}
};
void solve(){
int n;
cin>>n;
ST st(n);
vector<vector<int>> pos(n+1);
for(int i=1;i<=n;i++){
cin>>st.in1[i];
pos[st.in1[i]].push_back(i);
}
st.init();
int l=1,r=n;
int ans=0;
while(l<=r){
int mx=st.getMax(l,r);
ans++;
while(pos[mx].back()>r){
pos[mx].pop_back();
}
// cout<<mx<<" "<<pos[mx].back()<<endl;
r=pos[mx].back()-1;
pos[mx].pop_back();
// cout<<r<<endl;
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
}
C. Spring
纯纯小学数学题
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int a,b,c,m;
cin>>a>>b>>c>>m;
auto f=[&](int t1,int t2,int t3)-> int {
int ans=m/t1*6;
ans-=m/lcm(t1,t2)*3;
ans-=m/lcm(t1,t3)*3;
ans+=m/lcm(t1,lcm(t2,t3))*2;
return ans;
};
// f(a,b,c);
cout<<f(a,b,c)<<" "<<f(b,a,c)<<" "<<f(c,b,a)<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
}
D. Alternating Path
首先,如果存在奇环,这个环上的点一定不行。
因为题目中定义,如果一个点是美丽的,则这个点出去的所有路径都得是符合题意的。所以,这要这个点,能碰到奇环,就一定不行
所以对只要能被奇环联通的点,就一定不行
所以只需要对每个联通块判断是否存在奇环即可
染色法判奇环(存在奇环是 不是二分图 的充要条件,所以更普遍的叫法是染色法判定二分图)
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
void solve(){
int n,m;
cin>>n>>m;
vector<vector<int>> g(n+1);
vector<int> c(n+1,-1);
while(m--){
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
int ans=0;
for(int i=1;i<=n;i++){
if(c[i]!=-1) continue;
queue<int> q;
q.push(i);
c[i]=0;
int c0=1,c1=0,f=1;
while(q.size()){
int u=q.front();
q.pop();
for(auto v:g[u]){
if(c[v]==-1){
c[v]=c[u]^1;
if(c[v]==1) c1++;
else c0++;
q.push(v);
}
else if(c[v]==c[u]){
f=0;
}
}
}
if(f){
ans+=max(c1,c0);
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ct=1;
cin>>ct;
while(ct--){
solve();
}
}
E. Sum of Digits (and Again)
一共有 \(1e5\) 个数字,则数位和最大值也是 \(9e5\)
所以第二个数字一定是小于 \(9e5\) 的
枚举第二个数字即可,需要处理出,从第二个数字开始,后续的所有数位和,后续的每个数字消耗了多少个
对于每个字符串,直接 \(O(9*n)\) 的去枚举可能的第二个数字即可
赛时算错复杂度了,为了降复杂度写了个很抽象的类似哈希的东西,下面的代码是赛后补的
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
using pii=pair<int,int>;
using ll = long long;
using ull = unsigned long long;
const ll inf = 1e18;
const int mod = 998244353;
const int N=9e5+1;
/**
* 以 i 作为字符串中第二个出现的数字时
* 例:xxxxx,99999,45,9
*
* cnt:从 99999 开始,后面所有数位的计数
* sum:从 99999 开始,后面所有数位的和
*/
vector cnt(N,vector<int>(10));
vector<int> sum(N);
void init(){
for(int i=1;i<N;i++){
int val=i;
while(val){
cnt[i][val%10]++;
sum[i]+=val%10;
val/=10;
}
if(i>9){
val=sum[i];
for(int j=0;j<=9;j++){
cnt[i][j]+=cnt[sum[i]][j];
}
sum[i]+=sum[sum[i]];
}
}
}
void solve(){
string s;
cin>>s;
if(s.size()==1){
cout<<s<<endl;
return;
}
vector<int> c(10);
int t=0;
for(auto ch:s){
t+=ch-'0';
c[ch-'0']++;
}
auto check=[&](int val)->bool {
if(t-sum[val]!=val) return 0;
for(int i=0;i<=9;i++){
if(c[i]<cnt[val][i]) return 0;
}
return 1;
};
for(int i=1;i<=9*s.size();i++){
if(check(i)){
for(int j=0;j<=9;j++){
c[j]-=cnt[i][j];
}
for(int j=9;j>=0;j--){
for(int k=1;k<=c[j];k++){
cout<<j;
}
}
cout<<i;
int now=i;
while(now>9){
int tmp=0;
while(now){
tmp+=now%10;
now/=10;
}
cout<<tmp;
now=tmp;
}
cout<<endl;
return;
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
init();
int ct=1;
cin>>ct;
while(ct--){
solve();
}
}

浙公网安备 33010602011771号