Codeforces Round #820 (Div. 3) ABCDE(交互题)
//这场cf打得我。。。纯纯吃了交互题的亏
https://codeforces.com/contest/1729/problem/A
题目大意:
弗拉德现在在1楼。他打算叫电梯去他的公寓。
他家只有两部电梯。弗拉德很肯定地知道:
第一部电梯当前在楼层a上(它当前是静止的),
第二台电梯位于b层,前往c层(b≠c)。请注意,如果b=1,那么电梯已经离开1层,Vlad没有时间进入。
如果你呼叫第一部电梯,它将立即开始去第一层。如果你调用第二个,那么它首先会到达c层,然后才会去1层。每部电梯从x层移动到y层需要| x-y |秒。
弗拉德想叫一部更快到达他那里的电梯。帮他选这样的电梯。
inputCopy
3
1 2 3
3 1 2
3 2 1
outputCopy
1
3
2
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
int a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
cin>>T;
while(T--)
{
LL a,b,c;
cin>>a>>b>>c;
LL sum1=(a-1);
LL sum2;
if(b<c) sum2=(c-b)+(c-1);
else sum2=(b-1);
if(sum1<sum2) cout<<"1"<<endl;
else if(sum2==sum1) cout<<"3"<<endl;
else cout<<"2"<<endl;
}
return 0;
}
https://codeforces.com/contest/1729/problem/B
题目大意:
坡旅甲有一个由小写拉丁字母组成的字符串s。
他用下面的算法对它进行编码。
他从左到右检查字符串s的字母,对于每个字母,坡旅甲考虑它在字母表中的数字:
如果字母数是个位数(小于10),那么就直接写出来;
如果字母数字是一个两位数(大于或等于10),那么它写出来,并在后面加上数字0。
inputCopy
9
6
315045
4
1100
7
1213121
6
120120
18
315045615018035190
7
1111110
7
1111100
5
11111
4
2606
outputCopy
code
aj
abacaba
ll
codeforces
aaaak
aaaaj
aaaaa
zf
逆序判断即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
int a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
string s;
cin>>s;
vector<int> v;
for(int i=s.size()-1;i>=0;i--)
{
if(s[i]!='0') v.push_back(s[i]-'0');
else if(s[i]=='0')
{
v.push_back((s[i-2]-'0')*10+s[i-1]-'0');
i-=2;
}
}
//cout<<c<<endl;
reverse(v.begin(),v.end());
for(int i=0;i<v.size();i++)
{
//cout<<v[i]<<" ";
cout<<(char)(v[i]+96);
}
cout<<endl;
}
return 0;
}
https://codeforces.com/contest/1729/problem/C
题目大意:
给你一个由小写拉丁字母组成的字符串s。
最初,坡旅甲在该行的第一个瓦片上,并且想要通过跳到瓦片上来到达最后一个瓦片。
从第I个瓦片跳到第j个瓦片的代价等于|index(si)—index(sj)|,其中index(c)是字母表中字母c的索引(例如,index('a')=1,index('b')=2,...,index('z')=26)。
坡旅甲希望以最小的总成本到达第n块瓷砖,但同时进行最大数量的跳跃。
换句话说,在所有可能的方法中,他会选择跳跃次数最多的方法,以最小的总成本到达最后一块瓷砖。
坡旅甲最多可以访问每个瓷砖一次。
坡旅甲请你帮忙——打印出他应该跳转的字符串s的索引序列。
如果有多个答案,打印其中任何一个。
inputCopy
6
logic
codeforces
bca
aaaaaaaaaaa
adbaadabad
to
outputCopy
9 4
1 4 3 5
16 10
1 8 3 4 9 5 2 6 7 10
1 2
1 3
0 11
1 8 10 4 3 5 7 2 9 6 11
3 10
1 9 5 4 7 3 8 6 2 10
5 2
1 2
注意在排序的时候顺序和逆序的下标考虑
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
struct node
{
LL idx;
LL x;
}a[N];
bool cmp(node l,node r)
{
if(l.x!=r.x) return l.x<r.x;
else return l.idx<r.idx;
}
bool cmp2(node l,node r)
{
if(l.x!=r.x) return l.x<r.x;
else return l.idx>r.idx;
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
cin>>T;
while(T--)
{
string s;
cin>>s;
LL len=s.size();
LL sum=abs((s[0]-'a')-(s[len-1]-'a'));
cout<<sum<<" ";
for(LL i=0;i<s.size();i++)
{
a[i].idx=i+1;
a[i].x=(s[i]-'a');
}
vector<LL> v;
if(s[0]-'a'<=s[len-1]-'a')
{
sort(a,a+len,cmp);
bool flag=false;
for(LL i=0;i<len;i++)
{
if(a[i].idx==1) flag=true;
if(flag==true) v.push_back(a[i].idx);
if(a[i].idx==len) break;
}
}
else
{
sort(a,a+len,cmp2);
bool flag=false;
for(LL i=len-1;i>=0;i--)
{
if(a[i].idx==1) flag=true;
if(flag==true) v.push_back(a[i].idx);
if(a[i].idx==len) break;
}
}
cout<<v.size()<<endl;
for(LL i=0;i<v.size();i++)
cout<<v[i]<<" ";
cout<<endl;
v.clear();
s.clear();
}
return 0;
}
https://codeforces.com/contest/1729/problem/D
题目大意:
两个两个人为一组,组中所有xi值的总和不得超过组中yi值的总和。
朋友可以光顾餐厅的最大天数是多少?
inputCopy
6
6
8 3 9 2 4 5
5 3 1 4 5 10
4
1 2 3 4
1 1 2 2
3
2 3 7
1 3 10
6
2 3 6 9 5 7
3 2 7 10 6 10
6
5 4 2 1 8 100
1 1 1 1 1 200
6
1 4 1 2 4 2
1 3 3 2 3 4
outputCopy
2
0
1
3
1
3
感觉这题比A还简单hh,双指针
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
LL a[N],b[N],c[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
for(LL i=1;i<=n;i++)
cin>>a[i];
for(LL i=1;i<=n;i++)
{
cin>>b[i];
c[i]=b[i]-a[i];
}
sort(c+1,c+1+n);
//for(int i=1;i<=n;i++)
// cout<<c[i]<<" ";
//cout<<endl;
LL sum=0;
LL i=1,j=n;
while(i<j)
{
if(c[i]+c[j]<0) i++;
else
{
sum++;
i++;
j--;
}
}
cout<<sum<<endl;
}
return 0;
}
E 交互题
https://codeforces.com/contest/1729/problem/E
题目大意:
我们对你隐藏了一个n个顶点的循环图(3≤n≤10^18)。循环图是由n个顶点组成一个循环的无向图。
每个顶点属于一个循环,即循环的长度(其中边的数量)正好是n。循环中顶点的顺序是任意的。
您可以通过以下方式进行查询:
"?其中1≤a,b≤10^18,a≠b。作为对查询的响应,交互器在单独的行上输出从顶点a到顶点b的两条路径的随机长度,或者如果max(a,b)>n,则为-1。
交互器以相等的概率选择两条路径中的一条。路径的长度—是路径中的边数。
如果你通过不超过50次的查询猜出隐藏图中的顶点数(n ),你就赢了。
注意,交互器是以这样的方式实现的,对于任何有序对(a,b),它总是为query?a b”,不管有多少这样的查询。“注意了吗?交互者可能会以不同的方式回答一个问题。
图中的顶点是随机放置的,它们的位置是预先固定的。
陪审团有50项测试。
互动
您最多可以进行50次查询。要进行查询,请在单独的行上输出:
"?a b”,其中1≤a,b≤1018,a≠b。作为对查询的响应,交互器将在单独的行上输出从顶点a到顶点b的随机简单路径的长度(不要与从b到a的路径混淆),或者如果max(a,b)>n,则输出-1。交互器以相等的概率选择两条路径中的一条。
如果您的程序得到一个数字0作为查询结果,这意味着您的解决方案的结论已经被定义为“错误答案”(例如,您进行了50次以上的查询或进行了无效的查询)。在这种情况下,您的程序应该立即终止。否则,在这种情况下,您可能会得到一个随机的结论“执行错误”、“超过时间限制”或其他一些结论,而不是“错误答案”。
答案和查询一样,打印在单独一行上。在对它们进行计数时,答案的输出不被计为查询。要打印它,请使用以下格式:
"!n”:隐藏图形的预期大小(3≤n≤1018)。
之后,你的程序应该终止。
在下一个查询的输出之后,一定要使用流清理函数,这样一些输出就不会留在某个缓冲区中。例如,在C++中你应该使用函数flush(stdout),在Java中调用System.out.flush(),在Pascal中使用flush(output),在Python中使用stdout.flush()。
注意,交互器是以这样的方式实现的,对于任何有序对(a,b),它总是为query?a b”,不管有多少这样的查询。“注意了吗?交互者可能会以不同的方式回答一个问题。
图中的顶点是随机放置的,它们的位置是预先固定的。
inputCopy
1
2
-1
outputCopy
? 1 2
? 1 3
? 1 4
! 3
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=200200,M=2002;
LL query(LL a,LL b)
{
LL x;
cout<<"? "<<a<<" "<<b<<endl;
cin>>x;
return x;
}
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
//cin>>T;
while(T--)
{
for(LL i=2;i<27;i++)
{
LL x=query(1,i);
if(x==-1)
{
cout<<"! "<<i-1;
break;
}
LL y=query(i,1);
if(x!=y)
{
cout<<"! "<<x+y;
break;
}
}
}
return 0;
}