• 牛客题集:练习赛67、68


    练习赛67

    D

    dp[i][0]表示到了第i个位置,把前面的都变成0的最小操作数

    dp[i][1]表示到了第i个位置,把前面的都变成1的最小操作数

    最后输出min(dp[n][0],dp[n][1]+1))即可。

    #include <bits/stdc++.h>
    #define debug freopen("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double lf;
    typedef pair<ll, ll> pii;
    const int maxn = 1e6+10;
    const int N = 1500+10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9+7;
    const int hash_num = 131;
    const double eps=1e-6;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int n,a[maxn],f[maxn][2];
    int main()
    {
        #ifndef ONLINE_JUDGE
            debug;
        #endif
        n=read();
        for (int i = 1; i <= n; ++i)
        {
            a[i] =read();
        }
        if (a[1]) f[1][1]=0,f[1][0]=1;
            else f[1][1]=1,f[1][0]=0;
        for (int i = 2; i <= n; ++i)
        {
            if (a[i]==1)
            {
                f[i][0]=min(f[i-1][1]+1,f[i-1][0]+1);
                f[i][1]=min(f[i-1][1],f[i-1][0]+1);
            }
            else
            {
                f[i][0]=min(f[i-1][0],f[i-1][1]+1);
                f[i][1]=min(f[i-1][0]+1,f[i-1][1]+1);            
            }
        }
        cout << min(f[n][0],f[n][1]+1) <<endl;
        return 0;
    }
    View Code

    E

    需要建立虚点来优化的最短路问题

    #include <bits/stdc++.h>
    #define debug freopen("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double lf;
    typedef pair<ll, ll> pii;
    const int maxn = 1e6+35;
    const int N = 1500+10;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9+7;
    const int hash_num = 131;
    const double eps=1e-6;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    struct node{
        int to; ll dis;
        bool operator<(const node &b)const{
            return dis>b.dis;
        }
    };
    int n,t,a[maxn];
    bool vis[maxn];
    vector<int> v[maxn];
    
    ll dis[maxn];
    void dij(int s){ //s是起点,dis是结果
        memset(vis,0,sizeof(vis));
        memset(dis,INF,sizeof(dis)); 
        dis[s]=0; //last[s]=-1;
        static priority_queue<node> q; 
        q.push({s,0});
        while(!q.empty()){
            int u=q.top().to; q.pop();
            if(vis[u])continue; 
            vis[u]=1;
            for (ll j = 0; j < 32; ++j)
                if ((a[u]>>j)&1)
                {
                    for(auto p:v[j])
                    {
                        if(dis[p]>dis[u]+(1ll<<j)){
                            dis[p]=dis[u]+(1ll<<j);
                            q.push({p,dis[p]});
                            //last[p]=x; //last可以记录最短路(倒着)
                        }
                    }
                    v[j].clear();
                }
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
            debug;
        #endif
        t=read();
        while (t--)
        {
            n=read();
            for (int i = 0; i < 32; ++i) v[i].clear();
            for (int i = 1; i <= n; ++i)
            {
                a[i] =read();
            }
            for (int i = 1; i <= n; ++i)
            {
                for (ll j = 0; j < 32; ++j)
                {
                    if ((a[i]>>j)&1) v[j].pb(i);
                }
            }
            dij(1);
            if (dis[n] == INF) cout << "Impossible" <<endl;
                else cout << dis[n] <<endl;
        }
        return 0;
    }
    View Code

    F

    对于区间【l,r】的答案,我们可以通过线段树来查询,如何建树?

    假设【l,mid】的答案是 x1->y1的距离,【mid+1,r】的答案是 x2->y2的距离,那么【l,r】的答案肯定是 x1->y1、x1->y2、x2->y1、x2->y2这四个组合里面的最大那个。

    怎么求树上点与点之间的距离?套用lca即可。

    没调出来……

    练习赛68

    C

    考虑离线每次查询的L,在最小生成树的过程中,我们每次是从小往大加边的,将L也按从小到大排序,每次加到一个比当前L要大的边的时候,之前的那些已经连上的边一定是都比L小的,所以在这些联通块中的点,两两之间的d(u,v)一定是比L小的,也就是符合条件,那么这时符合条件的点对的数量就是C(sz,2)(sz为每个联通块的大小)。

    #include <bits/stdc++.h>
    #define debug freopen("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double lf;
    typedef pair<ll, ll> pii;
    const int maxn = 1e6+10;
    const int N = 1500+10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9+7;
    const int hash_num = 131;
    const double eps=1e-6;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    struct Edge
    {
        ll u,v,w;
        bool operator<(const Edge&x) const {
            return w<x.w;
        }
    }G[maxn];
    unsigned int SA, SB, SC; int n, m, q, LIM;
    ll L[maxn];
    unsigned int rng61(){
        SA ^= SA << 16;
        SA ^= SA >> 5;
        SA ^= SA << 1;
        unsigned int t = SA;
        SA = SB;
        SB = SC;
        SC ^= t ^ SA;
        return SC;
    }
    
    void gen(){
        scanf("%d%d%d%u%u%u%d", &n, &m, &q, &SA, &SB, &SC, &LIM);
        for(int i = 1; i <= m; i++){
            G[i].u = rng61() % n + 1;
            G[i].v = rng61() % n + 1;
            G[i].w = rng61() % LIM;
        }
        for(int i = 1; i <= q; i++){
            L[i] = rng61() % LIM;
        }
    }
    struct DSU{
        int a[maxn],sz[maxn];
        void init(int n){
            iota(a,a+n+1,0);
            fill(sz,sz+n+1,1);
        }
        int fa(int x){
            return a[x]==x?x:a[x]=fa(a[x]);
        }
        bool query(int x,int y){ //查找
            return fa(x)==fa(y);
        }
        void join(int x,int y){ //合并
            x=fa(x),y=fa(y);
            if(x==y)return;
            if(sz[x]>sz[y])swap(x,y);
            a[x]=y; sz[y]+=sz[x];
        }
        int operator[](int x){return fa(x);}
    }d;
    ll ans,res;
    int main()
    {
        #ifndef ONLINE_JUDGE
            debug;
        #endif
        gen();
        d.init(n);
        sort(L+1,L+1+q);
        sort(G+1,G+1+m);
        int pos=1;
        for (int i = 1; i <= m; ++i)
        {
            int x=d[G[i].u];
            int y=d[G[i].v];
            if (x!=y)
            {
                while (pos<=q && G[i].w>L[pos]) ans^=res,pos++;
                res += 1ll*d.sz[x]*d.sz[y];
                d.join(G[i].u,G[i].v);
            }
        }
        for (int i = pos; i <= q; ++i) ans^=res;
        cout << ans <<endl;
        return 0;
    }
    View Code

    D

    对于每个位置 i ,每个回合都只会由 i-1、i、i+1转移过来,那么就是

    对于每个位置做这样的转换,写出矩阵形式就是这样

     (图侵删)

     k轮不就是做k次转换就是k次方吗?

    但是普通快速幂的时间复杂度会超时,所以我们得知道什么是循环矩阵?

    循环矩阵介绍:https://www.luogu.com.cn/blog/water-mi/2333333-233333

    就可以把时间n^3降低乘n^2了。

    依旧是没调出来……

  • 相关阅读:
    java设计模式----工厂设计模式
    java拓展----CountDownLatch同步辅助类
    java设计模式----单例模式
    java拓展----Lock锁
    Orcal学习----初识Orcal
    java学习----泛型
    java学习----Junit&Log4j
    java学习----注解
    java学习----反射
    java学习----数据解析
  • 原文地址:https://www.cnblogs.com/Y-Knightqin/p/14454573.html
Copyright © 2020-2023  润新知