Codeforces Round #769 (Div. 2)思路分享

Codeforces Round #769 (Div. 2)

咕的最久的一场比赛.....当时被C卡住,真的让我自闭了许久。。。

A. ABC

发现合法的方案只有01和10,其余均为不合法。

B. Roof Construction

B题当时真的卡了我许久....
由于数字时0到n-1,也就是说二进制是从0,一个一个往上加的。考虑最高的位数,将所有的数字按照最高位是0,是1分成两堆。可以发现无论怎么安排,总有两个数异或起来会使最高位的1异或出来。最以最大值最小只能是最高位为1,其他位为0.方案也简单,将两拨分开放,中间交界处放0与1<<k即可。

C. Strange Test

真的没有看清楚a,b的数据范围.....一直在找什么贪心....结果卡住gg...
考虑我们使用过操作三后,一定存在a>=b,那么我们只能让b一直加1来与a相等。所以最后的结果一定是a加到某个数后,然后a|b,之后b++.或者b先加到某个数后,a|b,之后a++.因为数据大小都是1e6,所以我们直接枚举即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int T,a,b;  
int main()
{
//    freopen("1.in","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&a,&b);
        int ans=b-a;
        for(int i=1;i<=ans;++i)
        {
            if(((a+i-1)|b)==b)
            {
                ans=i;
                break;
            }
        }
        for(int i=1;i<=ans;++i)
        {
            if((a|(b+i-1))==b+i-1)
            {
                ans=i;
                break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

D. New Year Concert

题目要求前k个序列构成合法的序列,使得每个区间的gcd都不等于区间的长度。
首先想到的就是如果我们要修改的话,那么我们最优的就是将它修改成一个大质数,这样的话包括他在内的gcd都只能是1,造成的结果最优。并且修改后,整个序列就从修改的位置分开。
接下来我们就贪心的干,需要修改的话就修改就行了。现在的问题就是当我们添加一个数时,如何判断这个数需不需要修改。最朴素的想法就是将包含这个数的所有区间检查一遍,但这显然会超时....我们需要继续找性质....注意到:当我们从当前数向前扩展时,它的gcd只能不变或减小,而区间长度会增加。正好两者具有相反的单调性。假设存在某个区间不合法的话(即gcd=区间长度),那么之后他们的gcd与区间长度的大小关系正好相反。同时我们也很容易看出来最多只有一个区间不合法。这样直接二分。同时我们需要:随时查询某个区间的gcd,动态修改。直接套线段树就行了。

点击查看代码
#include<bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int N=2e5+10;
int n,a[N];
struct Tree
{
    int l,r,dat;
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define dat(p) t[p].dat
}t[N<<2];
inline int gcd(int a,int b) {return b?gcd(b,a%b):a;}
inline void build(int p,int l,int r)
{
    l(p)=l;r(p)=r;
    if(l==r) return;
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
}
inline void alter(int p,int x,int v)
{
    if(l(p)==r(p)) {dat(p)=v;return;}
    int mid=l(p)+r(p)>>1;
    if(x<=mid) alter(ls,x,v);
    else alter(rs,x,v);
    dat(p)=gcd(dat(ls),dat(rs));
}
inline int ask(int p,int l,int r)
{
    if(l<=l(p)&&r>=r(p)) return dat(p);
    int mid=l(p)+r(p)>>1;
    int ans=0;
    if(l<=mid) ans=gcd(ans,ask(ls,l,r));
    if(r>mid) ans=gcd(ans,ask(rs,l,r));
    return ans;  
}
inline bool check(int l,int r)
{
    if(a[r]>=1&&ask(1,l,r)<=r-l+1)
    {
        int L=l,R=r;
        while(L<R)
        {
            int mid=L+R+1>>1;
            if(ask(1,mid,r)<=r-mid+1) L=mid;
            else R=mid-1;
        }
        if(ask(1,L,r)==r-L+1) return true;
        return false;
    }  
    return false;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&a[i]);
    build(1,1,n);
    alter(1,1,a[1]);
    int l=1,ans=0;
    for(int i=1;i<=n;++i)
    {
        alter(1,i,a[i]);
        if(check(l,i))
        {
            l=i+1;
            ++ans;
        }
        printf("%d ",ans);
    }
    return 0;
}
posted @ 2022-02-20 22:32  逆天峰  阅读(87)  评论(0编辑  收藏  举报
作者:逆天峰
出处:https://www.cnblogs.com/gcfer//