• Educational Codeforces Round 33 (Rated for Div. 2)A-F


    总的来说这套题还是很不错的,让我对主席树有了更深的了解

    A:水题,模拟即可

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pii pair<int,int>
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=200+10,maxn=200000+10,inf=0x3f3f3f3f;
    
    int a[N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        cin>>n;
        int p1=1,p2=2;
        for(int i=0;i<n;i++)cin>>a[i];
        for(int i=0;i<n;i++)
        {
            if(a[i]!=p1&&a[i]!=p2)
            {
                cout<<"NO"<<endl;
                return 0;
            }
            else
            {
                if(a[i]==p2)swap(p1,p2);
                if(p1==1)
                {
                    if(p2==2)p2=3;
                    else p2=2;
                }
                else if(p1==2)
                {
                    if(p2==1)p2=3;
                    else p2=1;
                }
                else if(p1==3)
                {
                    if(p2==1)p2=2;
                    else p2=1;
                }
            }
        }
        cout<<"YES"<<endl;
        return 0;
    }
    /********************
    
    ********************/
    A

    B:给一个数n,找最大的n的余数是特定数,特定数是二进制前面k+1个1后面k个0的数,公式给出了,直接算出来然后从大到小遍历

    这题没给公式的话可能还可以做做,不过也不难推,但是给了公式就相当水了

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pii pair<int,int>
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=200+10,maxn=200000+10,inf=0x3f3f3f3f;
    
    int a[N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        for(int i=1;i<=10;i++)
            a[i]=((1<<i)-1)*(1<<(i-1));
        int n;
        cin>>n;
        for(int i=10;i>=1;i--)
        {
            if(n%a[i]==0)
            {
                cout<<a[i]<<endl;
                return 0;
            }
        }
        return 0;
    }
    /********************
    
    ********************/
    B

    C:找每个连通图里点权值最小相加即可,简单dfs

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pii pair<int,int>
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=100000+10,maxn=200000+10,inf=0x3f3f3f3f;
    
    vector<int>v[N];
    bool vis[N];
    ll c[N],cnt;
    void dfs(int u)
    {
        vis[u]=1;
        cnt=min(cnt,c[u]);
        for(int i=0;i<v[u].size();i++)
        {
            if(!vis[v[u][i]])
            {
                dfs(v[u][i]);
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>c[i];
        for(int i=0;i<m;i++)
        {
            int a,b;
            cin>>a>>b;
            v[a].pb(b);
            v[b].pb(a);
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                cnt=1e18;
                dfs(i);
                ans+=cnt;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    /********************
    
    ********************/
    C

    D:题意:刚开始账户里余额为0,余额不能超过k,每天早上你可以存钱,晚上有交易,可能增减,如果晚上交易为0,那么就需要查询账户,此时的账户余额不能为负数,问最少需要几天存钱,不行输出-1

    题解:先求一遍前缀和,然后对前缀和求一遍后缀最大值,然后从前往后扫,每次查询到余额为负的时候就根据后缀最大值来判断,然后加上最大能加的钱数,不能就输出-1

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pii pair<int,int>
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=100000+10,maxn=200000+10,inf=0x3f3f3f3f;
    
    ll a[N],sum[N],maxx[N];
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;ll d;
        cin>>n>>d;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)
        {
            sum[i]=sum[i-1]+a[i];
            if(sum[i]>d)
            {
                cout<<-1<<endl;
                return 0;
            }
        }
        maxx[n+1]=-1e18;
        for(int i=n;i>=1;i--)maxx[i]=max(maxx[i+1],sum[i]);
        ll cnt=0,ans=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]==0&&sum[i]+cnt<0)
            {
                ll x=max(d-maxx[i]-cnt,(ll)0);
            //    cout<<i<<"++++"<<x<<" "<<cnt<<" "<<maxx[i]<<" "<<d-maxx[i]-cnt<<endl;
                cnt+=x;
             /*   if(sum[i]+cnt>d)
                {
                    cout<<-1<<endl;
                    return 0;
                }*/
                ans++;
                if(a[i]==0&&sum[i]+cnt<0)
                {
               //     cout<<i<<" "<<sum[i]+cnt<<endl;
                    cout<<-1<<endl;
                    return 0;
                }
            }
            else if(sum[i]+cnt>d)
            {
                cout<<-1<<endl;
                return 0;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    /********************
    3 4
    -5 3 0
    3 5
    -5 -5 0
    ********************/
    D

    E:题意:给你x,y要求y个数相乘等于x的情况数

    题解:组合数,求出x的所有质因数的个数a,然后每次乘上C(y-1+a,y-1),,因为是隔板法,相当于y个盒子中放a个小球,有y-1个隔板,y-1+a个地方放y-1个隔板,所有情况就是C(y-1+a,y-1),没有放的地方就放上1,最后考虑有负数的情况,因为C(n,2)+C(n,4)+...=2^(n-1)乘上这个就好了

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define ll long long
    #define mp make_pair
    #define pb push_back
    #define mod 1000000007
    #define pii pair<int,int>
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    
    using namespace std;
    
    const int g=10.0,eps=1e-9;
    const int N=2000000+10,maxn=5000000+10,inf=0x3f3f3f3f;
    
    ll fac[N];
    ll quick(ll a,ll b)
    {
        ll ans=1;
        while(b)
        {
            if(b&1)ans=ans*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return ans;
    }
    int main()
    {
        /*ios::sync_with_stdio(false);
        cin.tie(0);*/
        fac[0]=1;
        for(int i=1;i<N;i++)fac[i]=fac[i-1]*i%mod;
        int q;
        scanf("%d",&q);
        while(q--)
        {
            ll x,y,ans=1;
            scanf("%lld%lld",&x,&y);
            for(ll i=2;i*i<=x;i++)
            {
                if(x%i==0)
                {
                    ll cnt=0;
                    while(x%i==0)cnt++,x/=i;
                 //   cout<<cnt<<endl;
                    ll inv=quick(fac[y-1]*fac[cnt]%mod,mod-2);
                    ans=ans*fac[y-1+cnt]%mod*inv%mod;
                }
            }
            if(x!=1)
            {
                ll cnt=1;
                ans=ans*y%mod;
            }
            printf("%lld
    ",ans*quick(2,y-1)%mod);
        }
        return 0;
    }
    /*******************
    C(y-1+x,y-1)*2^(y-1)%mod;
    (y-1+x)!
    (y-1)!(x)!
    *******************/
    E

    F:给你一棵树,每个节点有一个权值,q个查询每次查询x的子树中与x距离不超过k的权值最小的那个节点,强制在线

    题解:主席树维护,先dfs序建树,然后按照树节点深度从小到大来插入每个点,最后查询的时候找1到d【x】+k的那颗主席树,然后查询l【x】到r【x】的最小值就是答案了

    总结:主席树一般就是用来维护从1到x(x<=n)的所有区间的,可以方便的维护某一区间的权值,本质来说还是一颗线段树,主要是通过rt来访问是哪颗主席树

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define C 0.5772156649
    //#define ls l,m,rt<<1
    //#define rs m+1,r,rt<<1|1
    #define pii pair<int,int>
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=100000+10,maxn=200000+10,inf=0x3f3f3f3f;
    
    int a[N],d[N],l[N],r[N],num;
    int maxd,pos[N],res;
    int rt[N*20],ls[N*20],rs[N*20],value[N*20],tot;
    vector<int>v[N];
    void dfs(int u,int c,int f)
    {
        ++num;
        l[u]=num;
        d[u]=c;
        maxd=max(maxd,c);
        for(int i=0;i<v[u].size();i++)
        {
            int x=v[u][i];
            if(x==f)continue;
            dfs(x,c+1,u);
        }
        r[u]=num;
    }
    void build(int &o,int l,int r)
    {
        o=++tot;
        value[o]=1e9+10;
        if(l==r)return ;
        int m=(l+r)>>1;
        build(ls[o],l,m);
        build(rs[o],m+1,r);
    }
    void update(int &o,int l,int r,int last,int p,int va)
    {
        o=++tot;
        ls[o]=ls[last];
        rs[o]=rs[last];
        if(l==r)
        {
            value[o]=va;
            return ;
        }
        int m=(l+r)>>1;
        if(p<=m)update(ls[o],l,m,ls[last],p,va);
        else update(rs[o],m+1,r,rs[last],p,va);
        value[o]=min(value[ls[o]],value[rs[o]]);
    }
    int query(int o,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R)return value[o];
        int ans=1e9+10;
        int m=(l+r)>>1;
        if(L<=m)ans=min(ans,query(ls[o],l,m,L,R));
        if(R>m) ans=min(ans,query(rs[o],m+1,r,L,R));
        return ans;
    }
    void bfs(int n,int root)
    {
        queue<int>q;
        q.push(root);
        res=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
         //   cout<<u<<endl;
            pos[d[u]]=res;//对应深度在哪颗主席树中
            update(rt[res],1,n,rt[res-1],l[u],a[u]);
            res++;
            for(int i=0;i<v[u].size();i++)
            {
                int x=v[u][i];
                if(d[x]==d[u]+1)q.push(x);
            }
        }
    }
    void print(int o,int l,int r)
    {
        cout<<l<<" "<<r<<" "<<value[o]<<endl;
        if(l==r)return ;
        int m=(l+r)>>1;
        print(ls[o],l,m);
        print(rs[o],m+1,r);
    }
    int main()
    {
        /*ios::sync_with_stdio(false);
        cin.tie(0);*/
        int n,root;
        scanf("%d%d",&n,&root);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            v[a].pb(b);
            v[b].pb(a);
        }
        num=tot=0;
        dfs(root,1,-1);
       /* for(int i=1;i<=n;i++)
            cout<<l[i]<<" "<<r[i]<<" "<<d[i]<<endl;*/
        build(rt[0],1,n);
      //  print(rt[0],1,n);
        bfs(n,root);
     /*   for(int i=1;i<=n;i++)
            printf("%d
    ",pos[i]);*/
        int q,last=0;
        scanf("%d",&q);
        while(q--)
        {
            int x,k;
            scanf("%d%d",&x,&k);
            x=((x+last)%n)+1,k=(k+last)%n;
            k=k+d[x];k=min(k,maxd);
            last=query(rt[pos[k]],1,n,l[x],r[x]);
            printf("%d
    ",last);
        }
        return 0;
    }
    /********************
    5 2
    1 3 2 3 5
    2 3
    5 1
    3 4
    4 1
    2
    1 2
    2 3
    ********************/
    F
  • 相关阅读:
    websocket在线测试工具
    短信线上发送错误,线下成功
    nginx添加stream模块1.20
    sort 的使用
    实验、进程的同步与互斥——生产者消费者
    实验、可变分区存储管理系统模拟 —— 最先适应分配算法
    test
    c++的大数阶乘算法
    C#解析JSON字符串总结
    C++ 查看单个类对象模型利用Vs开发者命令提示工具
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7928894.html
Copyright © 2020-2023  润新知