• 10.11 上午 考试


    T1

    贪心的每次找最长的满足条件的序列,这样找到的一定是最少的

    证明:

    假如有更优的解,那么它在第一段一定是比贪心得出的第一段短一点,以此来满足后面的更少

    但是这个序列的元素越少,越有可能构成等差数列,所以贪心一定是最优解

    然后只需要判断相邻元素(不需要排序...)差的gcd==1和有没有相同元素

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    inline int read()
    {
        char q=getchar();int ans=0;
        while(q<'0'||q>'9')q=getchar();
        while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
        return ans;
    }
    const int N=100006;
    inline int abss(int x){return x<0?-x:x;}
    int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
    
    int n;
    int A[N];
    map<int,int> mp;
    
    int work()
    {
        int ans=1,num=0,gg;
        for(int i=1;i<=n;++i)
        {
            if(mp.count(A[i]))
            {
                ++ans;
                mp.clear();
                mp[A[i]]=1;
                num=1;
                continue;
            }
            mp[A[i]]=1;
            ++num;
            if(num==1)continue;
            if(num==2)
                gg=abss(A[i]-A[i-1]);
            else
                gg=gcd(gg,abss(A[i]-A[i-1]));
            if(gg==1)
            {
                ++ans;
                mp.clear();
                mp[A[i]]=1;
                num=1;
            }
        }
        return ans;
    }
    
    int main(){
    
        n=read();
        for(int i=1;i<=n;++i)
            A[i]=read();
        cout<<work();
    }
    T1

     

    T2

    暴力A题算法:

    交:得到的跟原来的连边(单向的)

    并:原来的跟得到的连边

    k=1时是双向边...

    然后从xdfs,能到y就行,标记不能用memset,时间戳即可

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    inline int read()
    {
        char q=getchar();int ans=0;
        while(q<'0'||q>'9')q=getchar();
        while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
        return ans;
    }
    const int N=250006;
    const int M=250006;
    const int ALLK=500006;
    struct son
    {
        int v,next;
    }a1[3000006];
    int first[3000006],e;
    void addbian(int u,int v)
    {
        a1[e].v=v;
        a1[e].next=first[u];
        first[u]=e++;
    }
    
    int n,m,ccc;
    int kk,op,tnum,tin1,tin2;
    
    int ff;
    
    int vis[N*3],tim;
    
    inline void dfs(int x)
    {
        vis[x]=tim;
        if(x==tin2)
        {
            ff=1;
            return ;
        }
        for(int i=first[x];i!=-1;i=a1[i].next)
        {
            if(vis[a1[i].v]==tim)
                continue;
            dfs(a1[i].v);
        }
    }
    
    int main(){
    
        //freopen("T2.in","r",stdin);
    
        mem(first,-1);
    
        n=read();m=read();
        ccc=n;
        for(int i=1;i<=m;++i)
        {
            kk=read();
            if(kk==0)
            {
                ++ccc;
                op=read();
                tnum=read();
                for(int j=1;j<=tnum;++j)
                {
                    tin1=read();
                    if(tnum==1)
                    {
                        addbian(ccc,tin1);
                        addbian(tin1,ccc);
                    }
                    else
                    {
                        if(op==0)
                            addbian(ccc,tin1);
                        else
                            addbian(tin1,ccc);
                    }
                }
            }
            else
            {
                tin1=read();tin2=read();
                ff=0;++tim;
                dfs(tin1);
                printf("%d
    ",ff);
            }
        }
    }
    T2

     

    正解是一个离线的算法,用dfs序

    T3

    有三种算法:

    1.线段树(维护f[j]+B[j]和f[j]-sum[j])

    直接维护区间最小值即可

    2.线段树(维护f[j]+B[j]和一段区间[L,R] f[j]+$sum_{k=j+1}^{L-1}$的最小值)

    我考试时打的,可惜前两种算法在二分的时候我忘了对 i+k取min,结果i+K>n,然后就挂了...

    3.正解:

    维护两个堆:q一个维护f[j]+B[j],w一个维护f[j]-sum[j]

    然后先往q里塞,取的时候先把i-j>K的扔掉,在把f[j]+B[j]<f[j]-sum[j]+sum[i]的塞进w里

    再把f[i]对q和w取min

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    inline ll read()
    {
        char q=getchar();ll ans=0;
        while(q<'0'||q>'9')q=getchar();
        while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
        return ans;
    }
    const int N=1000006;
    
    int n,K;
    ll A[N],B[N];
    ll pre[N];
    ll INF;
    
    ll f[N];
    
    ll er(int now,int l,int r)
    {
        ll ans=INF;
        int mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if( pre[mid]-pre[now]>B[now]&&ans>mid )
                ans=mid;
            if(l>=r)
                break;
            if( pre[mid]-pre[now]>B[now] )
                r=mid-1;
            else
                l=mid+1;
        }
        return ans;
    }
    
    struct TTTTTTTTTTTTTTTTTTTTTTTTTTTT__________________________TTTTTTTTTTTTTTTTTTTTTTTTTTTT
    {
        ll a[N*5],ji[N*5];
        void clear(){mem(a,0x7f);mem(ji,0x7f);}
        void pushup(int x){a[x]=(a[x<<1]<a[x<<1|1]?a[x<<1]:a[x<<1|1]);}
        void pushdown(int x)
        {
            if(ji[x]!=INF)
            {
                ji[x<<1]=(ji[x<<1]<ji[x]?ji[x<<1]:ji[x]);
                ji[x<<1|1]=(ji[x<<1|1]<ji[x]?ji[x<<1|1]:ji[x]);
                a[x<<1]=(a[x<<1]<ji[x]?a[x<<1]:ji[x]);
                a[x<<1|1]=(a[x<<1|1]<ji[x]?a[x<<1|1]:ji[x]);
                ji[x]=INF;
            }
        }
        void add(int L,int R,ll c,int l,int r,int x)
        {
            if(L>R)return ;
            if(L<=l&&r<=R)
            {
                a[x]=(a[x]<c?a[x]:c);
                ji[x]=(ji[x]<c?ji[x]:c);
                return ;
            }
            pushdown(x);
            int mid=(l+r)>>1;
            if(L<=mid)
                add(L,R,c,l,mid,x<<1);
            if(mid<R)
                add(L,R,c,mid+1,r,x<<1|1);
            pushup(x);
        }
        ll qq(int pos,int l,int r,int x)
        {
            if(l==r)
                return a[x];
            pushdown(x);
            int mid=(l+r)>>1;
            if(pos<=mid)
                return qq(pos,l,mid,x<<1);
            else
                return qq(pos,mid+1,r,x<<1|1);
        }
    }T[2];
    
    ll work()
    {
        mem(f,0x7f);f[0]=0;
        INF=f[1];
        ll tpos,tv,t1,t2;
        T[0].clear();T[1].clear();
        tpos=er(0,1,K);
        if(tpos==INF)tpos=K+1;
        T[0].add(1,tpos-1,f[0]+B[0],1,n,1);
        T[1].add(tpos,min(K,n),f[0]-pre[0],1,n,1);
        for(int i=1;i<=n;++i)
        {
            t1=T[0].qq(i,1,n,1);
            t2=T[1].qq(i,1,n,1)+pre[i];
            f[i]=(t1<t2?t1:t2);
            tpos=er(i,i+1,std::min(i+K,n));
            if(tpos==INF)tpos=i+K+1;
            T[0].add(i+1,tpos-1,f[i]+B[i],1,n,1);
            T[1].add(tpos,std::min(i+K,n),f[i]-pre[i],1,n,1);
        }
        return f[n];
    }
    
    int main(){
    
        // freopen("T3.in","r",stdin);
        // freopen("T3.out","w",stdout);
    
        n=read();K=read();
        for(int i=1;i<=n;++i)
        {
            A[i]=read();
            pre[i]=pre[i-1]+A[i];
        }
        for(int i=0;i<n;++i)
            B[i]=read();
        cout<<work();
    }
    算法1

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    inline int read()
    {
        char q=getchar();int ans=0;
        while(q<'0'||q>'9')q=getchar();
        while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
        return ans;
    }
    const int N=1000006;
    const int MAXK=100006;
    
    int n,K;
    int A[N],B[N];
    ll f[N],pre[N];
    ll INF;
    
    ll er(int now,int l,int r)
    {
        ll ans=INF;
        int mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if( pre[mid]-pre[now]>B[now]&&ans>mid )
                ans=mid;
            if(l>=r)
                break;
            if( pre[mid]-pre[now]>B[now] )
                r=mid-1;
            else
                l=mid+1;
        }
        return ans;
    }
    
    struct T_T
    {
        ll a[N*5],ji[N*5];
        void clear()
        {
            mem(a,50);
            mem(ji,50);
        }
        void pushup(int x)
        {
            a[x]=min(a[x<<1],a[x<<1|1]);
        }
        void pushdown(int x)
        {
            if(ji[x]!=INF)
            {
                ji[x<<1]=min(ji[x<<1],ji[x]);
                ji[x<<1|1]=min(ji[x<<1|1],ji[x]);
                a[x<<1]=min(a[x<<1],ji[x]);
                a[x<<1|1]=min(a[x<<1|1],ji[x]);
                ji[x]=INF;
            }
        }
        void build(int l,int r,int x)
        {
            if(l==r)
            {
                a[x]=INF;
                ji[x]=INF;
                return ;
            }
            int mid=(l+r)>>1;
            build(l,mid,x<<1);
            build(mid+1,r,x<<1|1);
            pushup(x);
        }
        void add(int L,int R,ll c,int l,int r,int x)
        {
            if(L>R)
                return ;
            if(L<=l&&r<=R)
            {
                ji[x]=min(ji[x],c);
                a[x]=min(a[x],c);
                return ;
            }
            pushdown(x);
            int mid=(l+r)>>1;
            if(L<=mid)
                add(L,R,c,l,mid,x<<1);
            if(mid<R)
                add(L,R,c,mid+1,r,x<<1|1);
            pushup(x);
        }
        ll qq(int pos,int l,int r,int x)
        {
            if(l==r)
                return a[x];
            pushdown(x);
            int mid=(l+r)>>1;
            if(pos<=mid)
                return qq(pos,l,mid,x<<1);
            else
                return qq(pos,mid+1,r,x<<1|1);
        }
    }T1;
    
    struct TT_TT
    {
        ll a[N*5];
        void clear()
        {
            mem(a,50);
        }
        void build(int l,int r,int x)
        {
            if(l==r)
            {
                a[x]=INF;
                return ;
            }
            int mid=(l+r)>>1;
            build(l,mid,x<<1);
            build(mid+1,r,x<<1|1);
        }
        void add(int L,int R,ll c,int l,int r,int x)
        {
            //printf("T2add L=%d R=%d c=%lld l=%d r=%d x=%d
    ",L,R,c,l,r,x);
            if(L>R)
                return ;
            if(L<=l&&r<=R)
            {
                a[x]=min(a[x],c);
                return ;
            }
            int mid=(l+r)>>1;
            if(L<=mid)
                add(L,min(R,mid),c,l,mid,x<<1);
            if(mid<R)
            {
                ll ttt;
                if(L>mid)
                    ttt=0;
                else
                    ttt=pre[mid]-pre[L-1];
                add(max(mid+1,L),R,c+ttt,mid+1,r,x<<1|1);
            }
        }
        ll qq(int pos,int l,int r,int x)
        {
            if(l==r)
                return a[x]+A[l];
            int mid=(l+r)>>1;
            ll ans=INF;
            ans=min(ans,a[x]+pre[pos]-pre[l-1]);
            if(pos<=mid)
                ans=min(ans,qq(pos,l,mid,x<<1));
            else
                ans=min(ans,qq(pos,mid+1,r,x<<1|1));
            return ans;
        }
    }T2;
    
    void out11()
    {
        printf("
    ");
        for(int i=1;i<=n;++i)
            printf("%lld ",T1.qq(i,1,n,1)==INF?-1:T1.qq(i,1,n,1));
        printf("
    ");
        for(int i=1;i<=n;++i)
            printf("%lld ",T2.qq(i,1,n,1)==INF?-1:T2.qq(i,1,n,1));
        printf("
    ");
    }
    
    void dp()
    {
        mem(f,50);
        INF=f[0];
        f[0]=0;
        T1.clear();
        T2.clear();
        ll tpos;
        ll t1,t2;
        tpos=er(0,1,K);
        if(tpos==INF)tpos=K+1;
        T1.add(1,tpos-1,B[0],1,n,1);
        T2.add(tpos,std::min(K,n),pre[tpos-1],1,n,1);
        for(int i=1;i<=n;++i)
        {
            t1=T1.qq(i,1,n,1);
            t2=T2.qq(i,1,n,1);
            f[i]=(t1>t2?t2:t1);
            tpos=er(i,i+1,std::min(i+K,n));
            if(tpos==INF)tpos=i+K+1;
            T1.add(i+1,tpos-1,f[i]+B[i],1,n,1);
            T2.add(tpos,std::min(i+K,n),f[i]+pre[tpos-1]-pre[i],1,n,1);
            //out11();
        }
    }
    
    int main(){
        
        //freopen("T3.in","r",stdin);
        //freopen("T3.out","w",stdout);
    
        n=read();K=read();
        for(int i=1;i<=n;++i)
            A[i]=read(),pre[i]=pre[i-1]+A[i];
        for(int i=0;i<n;++i)
            B[i]=read();
        dp();
        cout<<f[n];
        /*printf("
    ");
        for(int i=1;i<=n;++i)
            printf("%lld ",f[i]);
        printf("
    ");*/
    }
    算法2
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    inline ll read()
    {
        char q=getchar();ll ans=0;
        while(q<'0'||q>'9')q=getchar();
        while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
        return ans;
    }
    const int N=1000006;
    
    struct son
    {
        int pos;
        ll val;
        son(){}
        son(int _pos,ll _val){pos=_pos;val=_val;}
        bool friend operator < (son a,son b)
        {
            return a.val>b.val;
        }
    };
    
    int n,K;
    ll A[N],B[N];
    ll pre[N];
    ll f[N];
    
    priority_queue<son> q,w;
    
    ll work()
    {
        mem(f,0x7f);
        f[0]=0;
        q.push( son(0,B[0]) );
        son temp,t1,t2;
        for(int i=1;i<=n;++i)
        {
            while(!q.empty())
            {
                temp=q.top();
    
                if(i-temp.pos>K)
                {
                    q.pop();
                    continue;
                }
                if(temp.val<f[temp.pos]-pre[temp.pos]+pre[i])
                {
                    q.pop();
                    w.push( son(temp.pos,f[temp.pos]-pre[temp.pos]) );
                    continue;
                }//printf("temp  pos=%d val=%lld
    ",temp.pos,temp.val);
                break;
            }
            while(!w.empty()&&i-w.top().pos>K)
                w.pop();
            if(!q.empty())
            {
                //printf("q  i=%d %lld
    ",i,q.top().val);
                f[i]=min(f[i],q.top().val);
            }
            if(!w.empty())
            {
                //printf("w  i=%d %lld
    ",i,w.top().val+pre[i]);
                f[i]=min(f[i],w.top().val+pre[i]);
            }
            q.push( son(i,f[i]+B[i]) );
        }
    
        /*printf("
    ");
        for(int i=1;i<=n;++i)
            printf("%lld ",f[i]);
        printf("
    ");*/
    
        return f[n];
    }
    
    int main(){
    
        // freopen("T3.in","r",stdin);
        // freopen("T3.out","w",stdout);
    
        n=read();K=read();
        for(int i=1;i<=n;++i)
        {
            A[i]=read();
            pre[i]=pre[i-1]+A[i];
        }
        for(int i=0;i<n;++i)
            B[i]=read();
        cout<<work();
    }
    算法3

    什么?你问我为什么考这么渣、炸、扎

    我能明天再说吗...

  • 相关阅读:
    进程与线程
    HTML——部分MP4在谷歌浏览器上无法播放
    Node——用http-proxy 做反向代理服务器
    jQuery——操作复选框(checkbox) attr checked不起作用
    ionic2——开发利器之Visual Studio Code 常用插件整理
    ionic2——开发利器之Visual Studio Code 常用快捷键
    ionic2常见问题——修改应用图标及添加启动画面(官方命令行工具自动生成)
    ionic2常见问题——启动后白屏问题
    ionic2常见问题——解决下载gradle-2.14.1-all.zip太慢或失败
    ionic2常见问题——cordova使用Gradle构建下载maven太慢,使用阿里云镜像
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7651010.html
Copyright © 2020-2023  润新知