A. Card Game
看最大值是否在the first player 的牌里面。

#include <bits/stdc++.h>
using namespace std;
int main()
{
     int t,n,k1,k2;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d%d",&n,&k1,&k2);
         int f=1,maxn=0;
         int x;
         for(int i=1;i<=k1;i++)
         {
             scanf("%d",&x);
             if(x>maxn)
                maxn=x;
         }
         for(int i=1;i<=k2;i++)
         {
            scanf("%d",&x);
            if(x>maxn)
            {
                maxn=x;
                f=2;
            }
         }
         if(f==1)
            printf("YES\n");
         else
            printf("NO\n");
     }
    return 0;
}

B. Interesting Subarray
这个题目,最开始的反应是确定相隔最近的最大值和最小值位置,通过这个来判断是否可以。但由于有重复的元素,要找到相隔最近的最大值和最小值的位置,复杂度太高。后来冷静下来发现,其实没必要。对于一个满足要求的序列,如果满足max-min>=k,那么该数组中必然有相邻的两个数其差值大于2。那么只要把原数组扫一遍,判断一下即可。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t,n,a,b;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        scanf("%d",&a);
        int f=0;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&b);
            if(f==0&&abs(a-b)>=2)
            {
                printf("YES\n");
                printf("%d %d\n",i-1,i);
                f=1;
            }
            a=b;
        }
        if(!f)
            printf("NO\n");
    }
}

C. Make Good
想了很久,实在没有思路。
假设数的和为sum,异或和为x.
Solution1:
首先我们先考虑一种情况:当sum<=2x,并且sum为偶数时,那么我们可以加上两个相同的数(2x-sum)/2,那么sum的值就可以变成2x,而x的值不变。
那么其他的情况能否转换为这种情况呢?
我们可以取一个大数res=(1LL<<50)+(sum%2),那么res+sum的值一定是一个大于(1<<50),并且小于 (1<<51)的一个偶数,而x ^ res,一定是一个大于等于(1<<50)的数,所以2x大于等于(1<<51)。
即sum<=2
x,那么就转化为上述的情形。
**主要还是会根据数据估计取值的范围,学会利用异或的知识。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum,x;
int main()
{
    int t,n,a;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        sum=0,x=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            sum+=a;
            x^=a;
        }
        ll res=(1LL<<50)+(sum%2);
        sum+=res;
        x^=res;
        ll t=2*x-sum;
        printf("3\n");
        printf("%lld %lld %lld\n",res,t/2,t/2);
    }
    return 0;
}

Solution2:
直接求出这两个数,一个数为x,一个为sum。
因为sum+x+x+sum=2*(x+sum)=2*(x^ x ^(x+sum))。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t,n,a;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        long long sum=0,x=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a);
            sum+=a;
            x^=a;
        }
        printf("2\n");
        printf("%lld %lld\n",x+sum,x);
    }
    return 0;
}

D. Strange Device
以前没有做过这种类型的题目。相当于是和系统交互。
用k+1次询问即可解决。
对于一个长度为k的序列而言,其中第m大的数是bm,第m+1大的数是bm+1,如果除去一个的一个数是小于等于bm的,那么查询的第m大的数就是bm+1,如果是大于bm的,那么查询的第m大的数是bm。所以依次把1~k+1个数除去,那么查询结果中,bm+1出现的次数为m,bm出现的次数为k+1-m,所以m的值即为最大值出现的次数。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,k,pos,num;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int cnt=0;
        int a[505]={0};
        for(int i=1;i<=k+1;i++)
        {
            cout<<"?";
            for(int j=1;j<=k+1;j++)
            {
                if(i!=j)
                   cout<<" "<<j;
            }
            cout<<endl;
            cout.flush();//Idleness limit exceeded
            cin>>pos>>num;
            a[++cnt]=num;
        }
        int maxn=a[1],m=0;
        for(int i=1;i<=cnt;i++)
        {
            if(a[i]>maxn)
                maxn=a[i];
        }
        for(int i=1;i<=cnt;i++)
        {
            if(a[i]==maxn)
                m++;
        }
        cout<<"! "<<m<<endl;
        cout.flush();//Idleness limit exceeded
    }
    return 0;
}

持续更新中。。。