我是靠谱客的博主 欣慰花卷,这篇文章主要介绍Codeforces Round #773 (Div. 2)简训导语涉及的知识点题目参考文献,现在分享给大家,希望可以做个参考。

Codeforces Round #773 (Div. 2)简训

  • 导语
  • 涉及的知识点
  • 题目
      • A Hard Way
      • B Power Walking
      • C Great Sequence
      • D Repetitions Decoding
      • E Anonymity Is Important
  • 参考文献

导语

稳定三个题,就是第一个题抽风错了很多次,以及队友剩4min痛失第四题

涉及的知识点

STL,思维,字符串

链接:Codeforces Round #773 (Div. 2)

题目

A Hard Way

题目大意:略

思路:一开始做只觉得有边平行x轴就行了,但是还要另一个点在平行边下方

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <bits/stdc++.h> #define int long long const int inf=0x3f3f3f3f; const int maxn=2e6+5; using namespace std; int t,x[3],y[3]; signed main() { ios::sync_with_stdio(0); cin.tie(0); cin >>t; while(t--) { for(int i=0; i<3; i++) cin >>x[i]>>y[i]; int res=0; for(int i=0; i<3; i++) if(y[i]==y[(i+1)%3]) {//平行线 if(y[(i+2)%3]<y[i]) {//另一个在平行线下面 res=abs(x[i]-x[(i+1)%3]); break; } } cout <<res<<endl; } return 0; }

B Power Walking

题目大意:略

思路:很容易就可以得出结论,首先如果人数小于数字种类,那么一定能使得总和为数字种类,否则就会有新的一个人只拿走一个数字(每个人至少一个),增加总和

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <bits/stdc++.h> #define int long long const int inf=0x3f3f3f3f; const int maxn=3e5+5; using namespace std; int t,n,a[maxn]; signed main() { ios::sync_with_stdio(0); cin.tie(0); cin >>t; while(t--) { cin >>n; for(int i=1; i<=n; i++)cin >>a[i]; sort(a+1,a+1+n);//排序,方便去重 int len=unique(a+1,a+1+n)-a-1; for(int i=1; i<=n; i++) //如果人数超过种类,那么一定会有新的人只拿一个 i>len?cout <<++len<<" ":cout <<len<<" "; cout <<endl; } return 0; }

C Great Sequence

题目大意:给出长度为n的序列和一个正整数x,判断能否将序列分成多对数,每对数的第一个数乘x等于第二个数,如果不能则判断至少加几个数能使得序列满足条件

思路:题目实际上是一个配对问题,贪心的去考虑,将序列排序,然后从小到大的进行配对,如果没有剩下的就代表需要插入新的数字

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <bits/stdc++.h> #define int long long const int inf=0x3f3f3f3f; const int maxn=3e5+5; using namespace std; int t,n,a[maxn],x; signed main() { ios::sync_with_stdio(0); cin.tie(0); cin >>t; while(t--) { cin >>n>>x; map<int,int>use;//统计个数用于配对 for(int i=1; i<=n; i++)cin >>a[i],use[a[i]]++; int ans=0; sort(a+1,a+1+n);//必须排序 for(int i=1; i<=n; i++) { int p=a[i]; if(use[p]==0)continue;//已经用完了 if(use[p*x]) use[p*x]--; else ans++; use[p]--;// } cout <<ans<<endl; } return 0; }

D Repetitions Decoding

题目大意:给出一共正整数序列,定义串联重复和相关操作:

  1. 一个串联重复的序列x长度必须是偶数2k,对前k个元素有 x i = x i + k x_i=x_{i+k} xi=xi+k
  2. 一个序列a可以被分成多个串联重复每个子段也是串联重复
  3. 每一次操作可以选择一个数字c然后向已有的序列中的任意位置插入连续两个c

现在判断给定的初始序列能否切割成多个串联重复(在可以操作的前提下),如果能,输出所有操作以及切分出来的串联重复子串长度

思路:如果存在数字出现的次数为奇数,那必然无解
现在来探讨一下如何构造串联重复,利用贪心的思路,每一步构造前面的串,构造完后集体删去,这样的话就可以不用考虑前面的影响而继续获得后面的串,以 [ 1 , 3 , 1 , 2 , 2 , 3 ] [1,3,1,2,2,3] [1,3,1,2,2,3]为例,第一个元素为1,那么找到下一个1,令两者匹配,单独拆出来,也就是 [ 1 , 3 , 1 ] [1,3,1] [1,3,1],想要其串联重复,需要在后一个1后面插3,于是得到 [ 1 , 3 , 1 , 3 , 3 ] [1,3,1,3,3] [1,3,1,3,3],将符合条件的去掉,与剩余的组合得到 [ 3 , 2 , 2 , 3 ] [3,2,2,3] [3,2,2,3],该串本身就是串联重复,因此构造完成,详见代码

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <bits/stdc++.h> #define ll long long #define INF 0x3f3f3f3f #define pii pair<int,int> using namespace std; vector<int> vi; void ins(int p,int c) { vi.insert(vi.begin()+p,c); vi.insert(vi.begin()+p,c); } void solve() { vi.clear(); map<int,bool> mii; vector<pii> q;//记录每次的操作 vector<int> d;//记录每次操作后得到的长度 int n; scanf("%d",&n); for(int i = 1; i<=n; i++) { int x; scanf("%d",&x); vi.push_back(x); mii[x]^=1;//记录是否为偶数 } map<int,bool>::iterator it=mii.begin(); for(; it!=mii.end(); it++)//判断是否有奇数 if(it->second) {//存在奇数就无解 printf("-1n"); return ; } int i = 0,p=0; while(i < n) { for(int j = i+1; j<n; j++) { if(vi[j]==vi[i]) {//找到两个数字相同 p=j; for(int k = 1; k < j-i; k++) { if(j+k>=n||vi[i+k]!=vi[j+k]) { //j+k>=n是防止因为越界而不能复制 //第二个条件是判断如果不能就复制 ins(j+k,vi[i+k]);//按照题设条件复制 n+=2; q.push_back(make_pair(j+k,vi[i+k])); } } d.push_back((p-i)*2);//相当于把p~i复制了一遍 break; } } i+=(p-i)*2; } cout << q.size() << endl; for(i = 0; i < q.size(); i++) cout << q[i].first << " " << q[i].second << endl; cout << d.size() << endl; for(i = 0; i < d.size(); i++) { cout << d[i]; if(i<d.size()-1) cout << " "; else cout << endl; } } int main() { int t = 1; scanf("%d",&t); while(t--) solve(); return 0; }

E Anonymity Is Important

题目大意:有一个01序列,但是不清楚哪些是0哪些是1,现在有以下3中操作

  1. l l l r r r 0 0 0:代表区间 [ l , r ] [l,r] [l,r]全是0
  2. l l l r r r 1 1 1:代表区间 [ l , r ] [l,r] [l,r]至少有一个1
  3. q q q i n d e x index index:询问下标为 i n d e x index index的元素是0还是1

输出每次询问的结果(不保证元素的值一定能确定下来)

思路:只有两种方法确定一个元素的值:直接区间全是0或者对于一个包含该元素的区间,其余元素都已确定,而且该区间至少有一个1,那么,不断缩小带1区间就可以更快的得到哪个元素是1,因此可以维护两个信息:未确定元素和带1区间
未确定元素在确定之后需要被删除,使用set维护可以二分查找删除,带1区间的维护使用map,键为左端点,值为右端点,比较相邻区间的右端点可以区间嵌套

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <bits/stdc++.h> #define int long long #define INF 0x3f3f3f3f using namespace std; int n,q; set<int>s; map<int,int>seq; signed main() { ios::sync_with_stdio(0); cin.tie(0); cin >>n>>q; for(int i=0; i<=n+1; i++)s.insert(i); while(q--) { int t; cin >>t; if(!t) { int l,r,x; cin >>l>>r>>x; if(x) {//如果区间内至少存在一个 auto i=seq.lower_bound(l); //找到区间左端点与l相等或更大的,查看是否被l,r覆盖 if(i!=seq.end()&&i->second<=r)continue; //如果覆盖了,那么跳过即可,因为区间已经更小了 seq[l]=r;//否则将左端点为l的区间缩小 i=seq.find(l);//查找左端点为l的位置 while(i!=seq.begin()&&r<=prev(i)->second)seq.erase(prev(i)); //如果l的前一个区间包含了l,r,删掉前面一个,因为区间已经缩小了 } else while(1) {//删除l,r之间的,代表一定为0 auto i=s.lower_bound(l);//二分查找比l大的值 if(*i>r)break; s.erase(i); } } else { int x; cin >>x; if(!s.count(x))cout <<"NOn";//如果不在,代表已经被排除,也就一定是0 else {//到这里来代表x的情况不确定 int l=*prev(s.find(x)),r=*next(s.find(x)); //找到其所属的最小不确定区间 auto i=seq.upper_bound(l);//查找被l刚好覆盖的左端点 if(i!=seq.end()&&i->first<=x&&i->second<r)cout <<"YESn"; //x在这个区间里,而这个区间里只有x没有确定下来(未确定的l和r不在这个区间内) else cout <<"N/An"; } } } return 0; }

参考文献

  1. codeforces 1641C Anonymity Is Important (思维好题,STL)

最后

以上就是欣慰花卷最近收集整理的关于Codeforces Round #773 (Div. 2)简训导语涉及的知识点题目参考文献的全部内容,更多相关Codeforces内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部