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\n",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\n",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("\n");
    for(int i=1;i<=n;++i)
        printf("%lld ",T1.qq(i,1,n,1)==INF?-1:T1.qq(i,1,n,1));
    printf("\n");
    for(int i=1;i<=n;++i)
        printf("%lld ",T2.qq(i,1,n,1)==INF?-1:T2.qq(i,1,n,1));
    printf("\n");
}

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("\n");
    for(int i=1;i<=n;++i)
        printf("%lld ",f[i]);
    printf("\n");*/
}
算法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\n",temp.pos,temp.val);
            break;
        }
        while(!w.empty()&&i-w.top().pos>K)
            w.pop();
        if(!q.empty())
        {
            //printf("q  i=%d %lld\n",i,q.top().val);
            f[i]=min(f[i],q.top().val);
        }
        if(!w.empty())
        {
            //printf("w  i=%d %lld\n",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("\n");
    for(int i=1;i<=n;++i)
        printf("%lld ",f[i]);
    printf("\n");*/

    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

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

我能明天再说吗...

posted @ 2017-10-11 15:53  A_LEAF  阅读(153)  评论(0编辑  收藏  举报