《Codeforces Round #669 (Div. 2)》

A:又又又读错题了~

如果1和0的个数一样,就删完1.

如果0的个数多,也删完0.

然后1的个数多,那就留下偶数个1即可

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
const int N = 1e3+5;
const int M = 1e6+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;

int a[N];
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        int n;n = read();
        int cnt0 = 0,cnt1 = 0;
        for(rg int i = 1;i <= n;++i) 
        {
            a[i] = read();
            if(a[i] == 1) cnt1++;
            else cnt0++;
        }
        if(cnt1 > cnt0)
        {
            if(cnt1%2 == 0)
            {
                printf("%d\n",cnt1);
                for(rg int i = 1;i <= n;++i) if(a[i] == 1) printf("1 ");
            }
            else 
            {
                printf("%d\n",cnt1-1);
                int f = 0;
                for(rg int i = 1;i <= n;++i) 
                {
                    if(a[i] == 1)  
                    {
                        if(f) printf("1 ");
                        f = 1;
                    }
                }
            }
        }
        else if(cnt0 > cnt1)
        {
            printf("%d\n",cnt0);
            for(rg int i = 1;i <= n;++i) if(a[i] == 0) printf("0 ");
        }
        else 
        {
            printf("%d\n",cnt0);
            for(rg int i = 1;i <= n;++i) if(a[i] == 0) printf("0 ");
        }
        printf("\n");
    } 
 //   system("pause"); 
}
View Code

B:首先最大的肯定放最前面。

然后就暴力找一下和前面的gcd取gcd更大的点,然后放入。

如果出现多个点gcd都能最大,可以任意放哪个,因为c只是他们的gcd,且后面找位置都是用gcd去更新,所以只有gcd有影响

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 1e3+5;
const int M = 2e5+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;

int a[N],b[N],vis[N];
int main()
{
    int ca;ca = read();
    while(ca--)
    {
        int n;n = read();
        for(rg int i = 1;i <= n;++i) a[i] = read();
        memset(vis,0,sizeof(vis));
        sort(a+1,a+n+1);
        b[1] = a[n],vis[n] = 1;
        int gcd = b[1];
        for(rg int i = 2;i <= n;++i)
        {
            int mx = -1,pos;
            for(rg int j = n;j >= 1;--j)
            {
                if(!vis[j] && __gcd(gcd,a[j]) > mx)
                {
                    mx = __gcd(gcd,a[j]);
                    pos = j;
                }
            }
            gcd = mx,b[i] = a[pos],vis[pos] = 1;
        }
        for(rg int i = 1;i <= n;++i) printf("%d%c",b[i],i == n ? '\n' : ' ');
    }
}
View Code

C:很有意思的一个交互题~

有这样一个结论:

小的数 mod 大的数  一定 > 大的数 mod 小的数。

这也非常好证明。

设a = 小的数,b = 大的数.

a mod b = a。b mod a = [0,a)。

因为我们可以去询问最大2*n次。

然后我们可以两次询问a mod b 和 b mod a。

就能把小的那个数确定下来。

然后找n次即可。注意最后的留下的数是n且不会再判断

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<string,int> pii;
const int N = 1e4+5;
const int M = 2e5+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;

int a[N];
int main()
{
    int n;n = read();
    int st = 1;
    for(rg int i = 2;i <= n;++i)
    {
        printf("? %d %d\n",st,i);
        fflush(stdout);
        int mod1;mod1 = read();//st%i
        printf("? %d %d\n",i,st);
        fflush(stdout);
        int mod2;mod2 = read();//i%st
        if(mod1 < mod2)
        {
            a[i] = mod2;
        }
        else
        {
            a[st] = mod1;
            st = i;
        }
    }
    a[st] = n;
    printf("! ");
    for(rg int i = 1;i <= n;++i) printf("%d%c",a[i],i == n ? '\n' : ' ');
    fflush(stdout);
}
View Code

D:其实这个题目没有那么难(但还是挺难的

首先显然是一个单调队列或者单调栈优化的dp。

主要是怎么去优化,这里一开始想单调队列想了好久都没想清楚。

Solution:我们可以去维护一个单调递减和单调递增的栈。

对于单调递增栈来说。

因为是单调递增,所以当a[i] < a[top]时。

我们就可以边退栈变更新。因为每一次退栈时都满足之前退的元素 > a[i]和a[top],那么显然就能更新出。

注意我们退完后的栈顶,刚好也是满足之前退栈的元素全都 > a[i]和a[top]的。所以对栈顶再求一次最小的dp。

那么也可以发现,我们中间退栈的时候需要保持严格的大于才能退栈。

那么也就会导致我们栈中可能会有连续重复的元素,这时显然要无法满足更新条件,因为中间都相同的话也不满足条件。

所以我们要对相同的也进行退栈。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 3e5+5;
const int M = 2e5+5;
const LL Mod = 1e9+7;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define CT0 cin.tie(0),cout.tie(0)
#define IO ios::sync_with_stdio(false)
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    void print(int x){
        if(x < 0){x = -x;putchar('-');}
        if(x > 9) print(x/10);
        putchar(x%10+'0');
    }
}
using namespace FASTIO;

int a[N],dp[N],S1[N],S2[N];//递减栈,递增栈
int main()
{
    int n;n = read();
    for(rg int i = 1;i <= n;++i) a[i] = read();
    memset(dp,0x3f,sizeof(dp));
    dp[1] = 0;
    int top1 = 0,top2 = 0;
    S1[++top1] = 1,S2[++top2] = 1;
    for(rg int i = 2;i <= n;++i)
    {
        dp[i] = min(dp[i],dp[i-1]+1);

        while(top1 != 0 && a[i] > a[S1[top1]]) dp[i] = min(dp[i],dp[S1[top1--]]+1);
        if(top1 != 0) dp[i] = min(dp[i],dp[S1[top1]]+1);
        while(top1 != 0 && a[S1[top1]] == a[i]) top1--;
        S1[++top1] = i;

        while(top2 != 0 && a[i] < a[S2[top2]]) dp[i] = min(dp[i],dp[S2[top2--]]+1);
        if(top2 != 0) dp[i] = min(dp[i],dp[S2[top2]]+1);
        while(top2 != 0 && a[S2[top2]] == a[i]) top2--;
        S2[++top2] = i;
    }
    //for(rg int i = 1;i <= n;++i) printf("dp[%d] is %d\n",i,dp[i]);
    printf("%d\n",dp[n]);
}
View Code

 E:逮捕~

posted @ 2020-09-19 16:34  levill  阅读(129)  评论(0编辑  收藏  举报