【洛谷】P3686[CERC2016]爵士之旅 Jazz Journey -贪心

版权声明:侵删,转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/82156371

传送门:luogu3686


题解

五次贪心:

  • 正反都全部用单程票
  • 正向尽可能用双程票,反向用单程
  • 正向尽可能用双程票,反向尽可能用双程票
  • 反向尽可能用双程票,正向用单程
  • 反向尽可能用双程票,正向尽可能用双程票

每次填的顺序决定了用的票会不一样。
贪心显然是正确的。
卡卡常才过。不用 m a p 排序找才是真理!(虽然写起来麻烦了一点,雾)


代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+100,inf=0x7fffffff;
const ll INF=9e18;
int n,d,m,w[5],exi[N],to[N];
ll ans;
struct P{
  int u,v,id,op;
  P(){}
  P(int U,int V,int ID,int OP){u=U;v=V;id=ID;op=OP;}
}le[N];
struct Q{
    int u,v,val,op,typ;
    Q(){}
    Q(int U,int V,int VAL,int OP,int TYP){u=U;v=V;val=VAL;op=OP;typ=TYP;}
}qr[N];

char c,s[5];
inline void rd(int &x)
{
    c=getchar();x=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar()) x=x*10+(c^48);
}

inline bool cmp(const P&x,const P&y)
{
    if(x.u!=y.u) return x.u<y.u;
    if(x.v!=y.v) return x.v<y.v;
    return x.id<y.id;
}

inline bool cmq(const Q&x,const Q&y)
{
    if(x.u!=y.u) return x.u<y.u;
    if(x.v!=y.v) return x.v<y.v;
    if(x.op!=y.op) return x.op<y.op;
    if(x.typ!=y.typ) return x.typ<y.typ;
    return x.val<y.val;
}

int main(){
    register int i,j,k,t,pre,nw,ix,iy,iz,last,ks;ll res,sum,ss;
    rd(n);rd(d);rd(pre);
    for(i=1;i<d;++i,pre=nw){
       rd(nw);
       if(pre>nw) le[i]=P(nw,pre,i,1);
       else le[i]=P(pre,nw,i,0);
    }  
    sort(le+1,le+d,cmp);
    for(i=1;i<d;i=j){
        ix=le[i].u;iy=le[i].v;
        for(j=i+1;le[j].u==ix && le[j].v==iy && j<d;++j);
        to[i]=j;
    }

    rd(m);
    for(i=1;i<=m;++i){
        rd(ix);scanf("%d%s",&iy,s);rd(iz);
        if(ix<iy) qr[i]=Q(ix,iy,iz,0,s[0]=='O'?0:1);
        else qr[i]=Q(iy,ix,iz,1,s[0]=='O'?0:1);
    }
    sort(qr+1,qr+m+1,cmq);

    for(ks=1,i=1;i<d;i=j){
        ix=le[i].u,iy=le[i].v;
        w[0]=w[1]=w[2]=w[3]=inf;
        for(;qr[ks].u!=ix || qr[ks].v!=iy;ks++);
        if(qr[ks].op==0){
            if(qr[ks].typ==0){
                w[0]=qr[ks].val;
                for(;qr[ks].op==0 && qr[ks].typ==0 && qr[ks].u==ix && qr[ks].v==iy;ks++);
            }
            if(qr[ks].op==0 && qr[ks].typ==1 && qr[ks].u==ix && qr[ks].v==iy) 
             w[2]=qr[ks].val;
        }
        for(;qr[ks].op==0 && qr[ks].u==ix && qr[ks].v==iy;ks++);
        if(qr[ks].op==1 && qr[ks].u==ix && qr[ks].v==iy){
            if(qr[ks].typ==0){
                w[1]=qr[ks].val;
                for(;qr[ks].op==1 && qr[ks].typ==0 && qr[ks].u==ix && qr[ks].v==iy;ks++);
            }
            if(qr[ks].op==1 && qr[ks].typ==1 && qr[ks].u==ix && qr[ks].v==iy)
             w[3]=qr[ks].val;
        }
        res=INF;j=to[i];
        w[0]=min(w[0],w[2]);w[1]=min(w[1],w[3]);

        for(sum=0,k=i;k<j;++k) sum+=w[le[k].op];
        res=min(res,sum);

        if(w[2]<inf){
             for(sum=0,last=0,k=i;k<j;++k) if(!le[k].op){
             last=max(k,last);
             for(t=last+1;t<j;++t){
                if(le[t].op){
                    exi[t]=exi[k]=1;
                    last=t;
                    sum+=w[2];
                    break;
                }
             }
               if(t>=j) break;
             }

            for(ss=0,k=i;k<j;++k) if(!exi[k]) ss+=w[le[k].op];
            res=min(res,sum+ss);
        if(w[3]<inf){
            for(ss=0,last=0,k=i;k<j;++k) if(!exi[k] && le[k].op){
              last=max(last,k);
              for(t=last+1;t<j;++t) if(!exi[t] && (!le[t].op)){
                 exi[t]=exi[k]=1;
                 ss+=w[3];
                 last=t;
                 break;
              }
              if(t>=j) break;
            }
            for(k=i;k<j;++k) if(!exi[k]) ss+=w[le[k].op];
            res=min(res,sum+ss);
           }
        }
        for(k=i;k<j;++k) exi[k]=1; 
        if(w[3]<inf){
            for(sum=0,last=0,k=i;k<j;++k) if(le[k].op){
              last=max(last,k);
               for(t=last+1;t<j;++t) if(!le[t].op){
                 exi[t]=exi[k]=0;
                 sum+=w[3];
                 last=t;
                 break;
              }
              if(t>=j) break;
            }

            for(ss=0,k=i;k<j;++k) if(exi[k]) ss+=w[le[k].op];
            res=min(res,sum+ss);

        if(w[2]<inf){
            for(ss=0,last=0,k=i;k<j;++k) if(exi[k] && (!le[k].op)){
              last=max(last,k);
              for(t=last+1;t<j;++t) if(exi[t] && le[t].op){
                exi[t]=exi[k]=0;
                last=t;
                ss+=w[2];
                break;
              }
              if(t>=j) break;
            }
            for(k=i;k<j;++k) if(exi[k]) ss+=w[le[k].op];
            res=min(res,sum+ss);
           }
        }

        ans+=res;
    }
    printf("%lld\n",ans);
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/82156371