Codeforces Round 859 (Div. 4)

评价:比较简单的一集,简单考察思维和最基础算法

E:交互题。看了oiwiki和codeforces的文章,之前看的abc文章忘了,打算写一篇总结特点和一些典型例题,还了解了其他题型。

Solution:回到本题:只需要利用前缀和优化每次二分答案,从输入里得到我们想要的信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//cout.flush();
void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
}
int l=1,r=n;
while(l<r){
cout<<"?"<<" ";
int mid=(l+r)>>1;
cout<<mid-l+1<<" ";
for(int i=l;i<=mid;i++)cout<<i<<" ";
cout<<endl;
//cout.flush();
int x;cin>>x;
if(a[mid]-a[l-1]!=x)r=mid;
else l=mid+1;
}
cout<<"!"<<" "<<l<<endl;
}

F:题意:给定一个nmn*m的矩阵,给定初始点的位置和速度方向,已经知道终点位置,问需要经过边界反射多少次才能到达终点?

Solution:对于反射问题不难想到周期,我们考虑最差情况第二次到达起点的时候遍历了所有方格点也就是n×mn\times m个点,算上初始方向,最多有四个方向,所以最多经历 4×n×m4\times n\times m的路程,意思是最大周期是这么多,再算下去一定会重复计算,没有意义。每次到边界的时候只需要判断速度和位置会不会导致下一步越界,如果越界,则速度取相反方向。

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
void solve(){
cin>>n>>m;
int x1,y1,x2,y2;cin>>x1>>y1>>x2>>y2;
string s;cin>>s;
int mx=4*n*m;
int dx=0,dy=0;
if(s[0]=='D')dx=1;
else dx=-1;
if(s[1]=='R')dy=1;
else dy=-1;
int cux=x1,cuy=y1;
int cnt=0;
while(mx--){
if(cux==x2&&cuy==y2){
cout<<cnt<<endl;
return ;
}
bool flag=0;
if(cux==1&&dx==-1)dx=1,flag=true;
if(cux==n&&dx==1)dx=-1,flag=true;
if(cuy==1&&dy==-1)dy=1,flag=true;
if(cuy==m&&dy==1)dy=-1,flag=true;

cux+=dx;cuy+=dy;
if(flag)cnt++;
}
cout<<-1<<endl;
}

G:题意:Subsequence Addition (Hard Version)

数列 aa 最开始只有一个数 11,你可以进行若干次操作,每次操作你可以选取最新数组中 kk 个数(kk 无限制,小于等于 aa 的大小即可),将这 kk 个数的和放入 aa 的任意一个位置。

给定一个长度为 nn 的序列 cc,问 aa 能否在进行n-1次操作后转为 cc

tt 组数据。

1n2×105,1ci2×105,1t10001\leq \sum n\leq2\times10^5,1\leq c_i\leq2\times10^5,1\leq t\leq1000

Solution:由于是子序列,发现排序不影响答案正确性。以背包视角思考问题,可以发现只要前i-1小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int n, m;
int a[N];

void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int sum=1;
bool flag=true;
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
if(a[i]>sum)flag=false;
if(i>1) sum+=a[i];
}
if(flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}