Codeforces Round 776 (Div. 3) Tutorial (zh)

Codeforces Round 776

Codeforces Round 776

  • A. Deletions of Two Adjacent Letters
  • B. DIV + MOD
  • C. Weight of the System of Nested Segments
  • D. Twist the Permutation
  • E. Rescheduling the Exam

A. Deletions of Two Adjacent Letters

Codeforces Round 776 (Div. 3) Tutorial (zh)_第1张图片
Example
input

5
abcde
c
abcde
b
x
y
aaaaaaaaaaaaaaa
a
contest
t

output

YES
NO
NO
YES

题意:

你可以删除相邻的两个字符,问多次操作后能不呢剩下一个字符为 c c c
每个测试给你一个字符串 s s s和一个字符 c c c

题解:

不难看出每次删除必定有一个偶数位的字符,那么反过来,如果该字符只出现在字符串 s s s的偶数位或者没出现那么一定NO
如果出现在了奇数位,那么最后就可以

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return ;}
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

string s;int n,x,y,i,j,k,l,r;float f;
char ch;
int a[N],b[N];
struct node{
    int x,i;
};
void solve();

void solve(){
    cin>>s>>ch;
    if(s.size()==1) { if (ch != s[0]) endn else endy}//可以不写这一行,(当时特判了,后知后觉)
    for(i=0;i<s.size();i++)
        if(s[i]==ch&&((i+1)&1))endy
    endn
}

signed main(){
    //IOS
    int _=1;
    cin>>_;
    while(_--)solve();
}

B. DIV + MOD

Codeforces Round 776 (Div. 3) Tutorial (zh)_第2张图片
Example
input

5
1 4 3
5 8 4
6 10 6
1 1000000000 1000000000
10 12 8

output

2
4
5
999999999
5

题意:

给你一个区间的左右端点 l , r l,r l,r,和一个数字 a a a
f a ( x ) = ( x / a ) ( 向下取整 ) + x m o d    a f_a(x)=(x/a)(向下取整)+x \mod a fa(x)=(x/a)(向下取整)+xmoda
max ⁡ f a ( x ) x ∈ [ l , r ] \max f_a(x) x\in[l,r] maxfa(x)x[l,r]

题解:

首先考虑 x m o d    a x\mod a xmoda最大,
其实考虑 x x x最大
最后取最大值

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return ;}
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

//string s;int n,x,y,i,j,k,l,r;float f;
//char ch;
//int a[N],b[N];
struct node{
    int x,i;
};
void solve();
void solve(){
    int l,r,a;
    cin>>l>>r>>a;
    int ans=r / a + r % a;
    int ans2=r / a * a - 1;
    if(ans2>=l)
        ans = max( ans, ans2 / a + ans2 % a );
    cout<<ans<<endl;
}

signed main(){
    //IOS
    int _=1;
    cin>>_;
    while(_--)solve();
}

C. Weight of the System of Nested Segments

Codeforces Round 776 (Div. 3) Tutorial (zh)_第3张图片
Codeforces Round 776 (Div. 3) Tutorial (zh)_第4张图片
Example
input

3

3 8
0 10
-2 1
4 10
11 20
7 -1
9 1
2 3
5 -2

3 6
-1 2
1 3
3 -1
2 4
4 0
8 2

2 5
5 -1
3 -2
1 0
-2 0
-5 -3

output

12
2 6
5 1
7 8

10
1 6
5 2
3 4

-6
5 1
4 2

题意:

给出 n n n, m m m
随后给出 m m m个坐标点和其权值
你需要给出 n n n个区间 [ l 1 , r 1 ] , [ l 2 , r 2 ] , . . . , [ l n , r n ] [l_1,r_1],[l_2,r_2],...,[l_n,r_n] [l1,r1],[l2,r2],...,[ln,rn]
要满足 i , j ( 1 ≤ i ≤ j ≤ n ) i,j(1\leq i \leq j \leq n) i,j(1ijn)使得 l i < l j < r j < r i l_i < l_j < r_j < r_i li<lj<rj<ri
求满足以上条件的区间 min ⁡ ∑ k = 1 n f ( k ) \min \sum_{k=1}^nf(k) mink=1nf(k), f ( x ) = w l x + w r x , w i 是 i 点的权值 f(x)=w_{l_x}+w_{r_x},w_i是i点的权值 f(x)=wlx+wrx,wii点的权值
简单来说就是找到 n n n个区间,区间之间构成严格包含关系,因为可以取很多种这样的区间,求构成区间的全部点的权值和的最小值

题解:

直接贪心,给权值排序
然后取点,在前 2 n 2n 2n个点之中排序(按照坐标大小),求和
最后打印点的编号即可

第一个排序可以保证权值求和后最小,第二个排序可以保证区间是严格包含关系

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return ;}
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

//string s;int n,x,y,i,j,k,l,r;float f;
//char ch;
//int a[N],b[N];
struct node{
    int x,w;
    int i;
};

void solve();
node a[N];
int n,m;

void solve(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>a[i].x>>a[i].w;
        a[i].i=i;
    }

    sort(a+1,a+m+1,[&](node a,node b){return a.w<b.w;});
    int ans=0;
    for(int i=1;i<=n*2;i++)ans+=a[i].w;
    sort(a+1,a+n*2+1,[&](node a,node b){return a.x<b.x;});

    cout<<ans<<'\n';
    for(int i=1;i<=n;i++){
        cout<<a[i].i<<' '<<a[n*2-i+1].i<<'\n';
    }
    cout<<'\n';
}

signed main(){
    //IOS
    int _=1;
    cin>>_;
    while(_--)solve();
}

D. Twist the Permutation

Codeforces Round 776 (Div. 3) Tutorial (zh)_第5张图片

Codeforces Round 776 (Div. 3) Tutorial (zh)_第6张图片
Example
input

3
6
3 2 5 6 1 4
3
3 1 2
8
5 8 1 3 2 6 4 7

output

0 1 1 2 0 4 
0 0 1 
0 1 2 0 2 5 6 2 

题意:

有一个排列放在数组 a a a,有 n n n次操作,第 x x x次操作可以右移 k k k a [ 1 , 2 , . . , x ] a[1,2,..,x] a[1,2,..,x]
现在给你操作 n n n次的数组 b b b,问你 n n n次操作分别都右移了多少次

题解:

其实反过来想就是第 n n n次操作会改变数字 n n n在数组里的原始位置,如果不右移则不动,直接反过来模拟计算即可

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return ;}
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;

//string s;int n,x,y,i,j,k,l,r;float f;
//char ch;
//int a[N],b[N];
struct node{
    int x,w;
    int i;
};

void solve();
int a[N],b[N];
int n,m;

void solve(){
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=n-1;i>=0;i--){
        b[i] = find(a,a+n,i+1)-a ;
        rotate(a,a+b[i]+1,a+i+1);
        
        b[i] = (b[i]+1)%(i+1);
    }
    for(int i=0;i<n;i++)cout<<b[i]<<" \n"[i==n-1];
}

signed main(){
    //IOS
    int _=1;
    cin>>_;
    while(_--)solve();
}

E. Rescheduling the Exam

Codeforces Round 776 (Div. 3) Tutorial (zh)_第7张图片
Codeforces Round 776 (Div. 3) Tutorial (zh)_第8张图片
input

9

3 12
3 5 9

2 5
1 5

2 100
1 2

5 15
3 6 9 12 15

3 1000000000
1 400000000 500000000

2 10
3 4

2 2
1 2

4 15
6 11 12 13

2 20
17 20

output

2
1
1
2
99999999
3
0
1
9

题意:

总共 m m m天,有 n n n次考试,给出 n n n次考试的时间
你可以调整一次考试时间,问最短休息时间(考试前的空闲时间)的最大值为多少

题解:

修改休息时间最短的那次考试,可以放在最后或者放在最长休息时间的中间
取改变和不改变的最大值
并且注意,大多数变体中的最小中断是相同的 — 初始时间表中的最小值。所以为了减少 μ μ μ
,您需要准确地移动形成它的两项考试之一,并且您需要检查两个选项中哪一个更好。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define IOS {std::ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);}
#define x first
#define y second
#define int long long
#define end(x) {cout<<x<<'\n';return ;}
#define endy {cout<<"YES\n";return ;}
#define endn {cout<<"NO\n"; return ;}
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
const int N =2*1e5+10;
const int inf = 0x3f3f3f3f;
//string s;int n,x,y,i,j,k,l,r;float f;
//char ch;
//int a[N],b[N];

void solve();
int f(int x);
int a[N];
int n,d;

int f(int x){
    int maxn=0,minn=d;
    int last_i=0;
    for(int i=1;i<=n;i++){
        if(i==x)continue;
        maxn=max(maxn, a[i]-a[last_i]-1);
        minn=min(minn, a[i]-a[last_i]-1);
        last_i=i;
    }
    return min(minn,max(d-a[last_i]-1,((maxn-1)/2)));
}
void solve() {
    cin >> n >> d;
    int min_ans_i = 1;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        if (a[min_ans_i] - a[min_ans_i - 1] - 1 > a[i] - a[i - 1] - 1)min_ans_i = i;
    }
    int ans=f(min_ans_i);
    if(min_ans_i>1)
        ans = max (ans,f(min_ans_i-1));
    cout<<ans<<'\n';
}

signed main(){
    IOS
    int _=1;
    cin>>_;
    while(_--)solve();
}

你可能感兴趣的:(CodeForces,算法,c++)