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;
}
posted @ 2022-09-13 17:57  Vijurria  阅读(86)  评论(0编辑  收藏  举报