Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)

A : A Variety of Operations

解题思路 :

~略

AC代码 :

#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>

using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py  puts("Yes")
#define pn  puts("No")
#define pcn  putchar('\n')
#define pcs  putchar(' ')
#define pc(a)  putchar(a)
#define pb(a)  push_back(a)
inline void intxt( ){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
}
inline int read( ){
    int f = 1,x = 0;
    char ch = getchar();

    while (ch < '0' || ch > '9')   {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
    return x;
}
const int maxn=5e5+5;

ll c,d;

int main(){
    txt;
    CAS{
        cin>>c>>d;
        if(c==d && c==0){
            cout<<0<<endl;
            continue;
        }
        if( abs(c-d)%2!=0 ){
            cout<<-1<<endl;
            continue;
        }
        if(c==d){
            cout<<1<<endl;
        }else{
            cout<<2<<endl;
        }
    }

    return 0;
}

B : Take Your Places!

题意:

给长度为n的a数组 , 问最少可以进行多少次交换相邻元素操作可以让数组奇数偶数不相邻
若无论多少次都无法满足条件 , 则输出-1 ,否则输出最少操作数

解题思路 :

首先 , 要满足奇偶不相邻,那么奇数和偶数的个数只差一定<=1
例如: 1 1 1 1 2 2就一定无法满足

然后我们要讨论n还是
n为奇时只能出现两种情况 :奇 偶 奇 偶 奇 或者偶 奇 偶 奇 偶
n为偶数时也只能出现两种情况 : 奇 偶 奇 偶 奇 偶或者偶 奇 偶 奇 偶 奇
知道了最终数组的情况也就好算最小交换次数了
假设初始数组a为 : 奇 偶 偶 奇 奇 偶 奇 奇 偶
那么我们最终的数组a就是 : 奇 偶 奇 偶 奇 偶 奇 偶 奇
以下我用1代表奇,2代表偶 ,如图 :
请添加图片描述
我们可以轻易地发现 : 地 i 个奇数最终必须到达地 2*i-1的位置 , 那么这个元素对答案的贡献就为 |第i个奇数的初始位置 - (2*i-1)| , 因为 第i个奇数初始位置可能在最终位置的左边或右边,所以要交绝对值
有点像贪心吧 , 我也不知道 , 大概就是这么求的 , 注意n为偶时 , 要讨论下奇元素在奇位置或者偶位置 , 然后取最小值

AC代码 :

#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>

using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py  puts("Yes")
#define pn  puts("No")
#define pcn  putchar('\n')
#define pcs  putchar(' ')
#define pc(a)  putchar(a)
#define pb(a)  push_back(a)
inline void intxt( ){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
}
inline int read( ){
    int f = 1,x = 0;
    char ch = getchar();

    while (ch < '0' || ch > '9')   {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
    return x;
}
const int maxn=2e5+5;

int n;
int a;
vector<int> ji;//奇元素的位置
vector<int> ou;//偶元素的位置
int jinum;
int ounum;

ll solveji(){//n为奇
    ll ans=0;
    if( jinum>ounum ){
        repi(i,0,jinum-1){
            ans+=abs( ji[i]-(i*2+1) );
        }
    }else{
        repi(i,0,ounum-1){
            ans+= abs( ou[i]-(i*2+1) );
        }
    }
    return ans;
}
ll solveou(){//n为偶
    ll ans=0;
    ll tem=0;
    repi(i,0,jinum-1){
        tem+= abs( ji[i]-(i*2+1) );
    }
    ans=tem;
    tem=0;
    repi(i,0,ounum-1){
        tem+= abs( ou[i]-(i*2+1) );
    }
    ans=min(ans,tem);
    return ans;
}

int main(){
    txt;
    CAS{
        cin>>n;
        ji.clear();
        ou.clear();
        repi(i,1,n){
            a=read();
            if(a%2==0){
                ou.pb(i);
            }else{
                ji.pb(i);
            }
        }
        jinum=ji.size();
        ounum=ou.size();
        if( abs(jinum-ounum)>1 ){//无论如何都不满足
            cout<<-1<<endl;
            continue;
        }
        if( n%2==1 ){
            cout<<solveji()<<endl;
        }else{
            cout<<solveou()<<endl;
        }
    }
    return 0;
}

C : Compressed Bracket Sequence

题意 :

输入的a奇位置表示有多少个(括号,偶位置表示)括号
求有多少对匹配的括号序列

解题思路 :

咋一看n的范围是1e3 , 那就大胆猜测是n^2的算法才对 , 也不好解释咋写, 直接看代码吧 , 有点像dp

补题AC代码 :

#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>

using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py  puts("Yes")
#define pn  puts("No")
#define pcn  putchar('\n')
#define pcs  putchar(' ')
#define pc(a)  putchar(a)
#define pb(a)  push_back(a)
inline void intxt( ){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
}
inline ll read( ){
    ll f = 1,x = 0;
    char ch = getchar();

    while (ch < '0' || ch > '9')   {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
    return x;
}
const int maxn=2e3+5;

int n;
ll a[maxn];
ll dp[maxn];//表示以地i个数字')'结尾的个数

int main(){
    txt;
    cin>>n;
    repi(i,1,n){
        a[i]=read();
    }
    ll ans=0,sum,ge;
    for(int i=1;i<=n;i+=2){
        sum=0;//记录重i+2个位置开始,一直到结尾未被匹配的'('
        ge=a[i];//记录i位置未被匹配的'('
        for(int j=i+1;j<=n;j++){//遍历须找以i为最后一对'('匹配的括号
            if( j%2==0 ){//j为偶表示')',可以开始匹配
                if( sum>=a[j] ){//如果中间的'('多于第j个位置的')',那么sum抽一部分与a[j]个')'匹配
                    sum-=a[j];//中间未匹配'('减少a[j]个
                    continue;
                }

                ll tem=a[j]-sum;
                sum=0;//昨晚少写了这句 , 一直wa在test 13 , 我太菜了, 中间的'('不够,终于可以用i位置的'('了,那么sum值为0,因为中间的全部被匹配了
                if(tem>ge){//  ')'比i位置的'('还多
                    ans+=ge+dp[i-1];
                    break;
                }else if( tem==ge ){//  '('与')'一样多
                    dp[j]=dp[i-1]+1; //用了地j位置的最后一个括号,则更新dp[j]
                    ans+=ge+dp[i-1];//还要加上i位置前一个位置刚好匹配完最后一个括号的数目
                    break;
                }else{
                    dp[j]=++;//用到了j位置最后一个')',则更新dp[j]
                    ans+=tem;
                    ge-=tem;//地i个位置的'('未使用完
                }

            }else{//'j'为奇,表示'('
                sum+=a[j];
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}

D : Take a Guess

题意 :

交互题 , 一个长度为n的数组 , 让你猜第k大的数字是什么 , 我们可以询问2*n次 ,
每次询问可以是以下两种 :
1 , 询问and i j 返回a[i] & a[j]
2 ,询问or i j 返回a[i] | a[j]

解题思路 :

题目给出最多询问2*n次,那我就尽管用满2*n就行了 , 我们可以发现
a&b + a|b==a+b
那如果我们这样询问出这样的结果
a[1]+a[2]==x12,a[2]+a[3]==x23,a[1]+a[3]==x13
那么就可以解除a了, a[1]=(x12-x23+x13)/2 a[2]=x12-a[1] a[3]=x13-a[2]
那么后面的数就可以递推求出了
a[4]=x34-a[3]
a[5]=x45-a[4]

补题AC代码 :

#include<iostream>
#include<queue>
#include<string>
#include<string.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<cmath>

using namespace std;
typedef long long ll;
#define repi(x,y,z) for(int x = y; x<=z;++x)
#define deci(x,y,z) for(int x = y; x>=z;--x)
#define repl(x,y,z) for(ll x = y; x<=z;++x)
#define decl(x,y,z) for(ll x = y; x>=z;--x)
#define gcd(a, b) __gcd(a, b)
#define lcm(a, b) (a * b / gcd(a, b))
#define INF 0x3f3f3f3f
#define ms(a,b) memset( a, b , sizeof (a) )
#define txt intxt()
#define CAS int casen;scanf("%d",&casen);for(int LP=1;LP<=casen;++LP)
#define py  puts("Yes")
#define pn  puts("No")
#define pcn  putchar('\n')
#define pcs  putchar(' ')
#define pc(a)  putchar(a)
#define pb(a)  push_back(a)
inline void intxt( ){
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
}
inline ll read( ){
    ll f = 1,x = 0;
    char ch = getchar();

    while (ch < '0' || ch > '9')   {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
    return x;
}
const int maxn=2e3+5;

int AND(int x,int y){
    printf("and %d %d\n",x,y);
    fflush(stdout);
    return (int)read();
}
int OR(int x,int y){
    printf("or %d %d\n",x,y);
    fflush(stdout);
    return (int)read();
}

int n,k;
vector<int> g;

int main(){
    //txt;
    cin>>n>>k;
    int add12=OR(1,2)+AND(1,2);
    int add23=OR(2,3)+AND(2,3);
    int add31=OR(1,3)+AND(1,3);

    int a=(add12-add23+add31)/2;
    int b=add12-a;
    int c=add31-a;

    g.pb(a);
    g.pb(b);
    g.pb(c);

    int pre=c;
    repi(i,4,n){
        int addxx=OR(i-1,i)+AND(i-1,i);
        pre=addxx-pre;
        g.pb(pre);
    }
    sort(g.begin(),g.end());
    cout<<"finish "<<g[k-1]<<endl;
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值