2017.10.19离线赛总结

来源:互联网 发布:矿山工程预算软件 编辑:程序博客网 时间:2024/06/05 00:12

vigenere ——4106

思路:水题,不解释。

game ——4107

思路:乍一看题意,求最大值最小,脑海中直接蹦出二分答案,然而看清楚题意,再看看数据范围,貌似可以贪心,且可以先估计按L或R 排序。
再仔细推出,答案应该是 max{ij=1Lj(LiRi)} 。
根据式子,可以看出是按照L*R来排序的。
首先,我们只知道ni=1Li,那么,若最后一个与倒数第二个交换一下,就会发现ans变了,也经过2小时的对拍…可以说是正确的,应该也是显然的。(比赛贪心哪要这么多的证明)

#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define N 1005#define L 4005#define P 10000#define LL long longusing namespace std;int n;struct node{    int a,b,id;    bool operator<(const node &_)const{        return a*b<_.a*_.b;    }}A[N];struct p60{    void chkmax(LL &x,LL y){if(x<y)x=y;}    LL a,b,ans;    void solve(){        scanf("%lld%lld",&a,&b);        REP(i,1,n)scanf("%d%d",&A[i].a,&A[i].b);        sort(A+1,A+1+n);        REP(i,1,n){            LL res=a/A[i].b;            chkmax(ans,res);            a*=A[i].a;        }        cout<<ans<<endl;    }}p60;struct p100{    struct Big{        int num[L],len;        Big(){            memset(num,0,sizeof(num));            len=1;        }        Big operator *(const int &a)const{            Big b;            b.len=len;            REP(i,0,len-1){                int &B=b.num[i];                B+=num[i]*a;                if(B>=P)b.num[i+1]+=B/P,B%=P;            }            if(b.num[b.len])b.len++;            return b;        }        Big operator /(const int &a)const{            Big b;            REP(i,0,len-1)b.num[i]=num[i];            DREP(i,len-1,1)b.num[i-1]+=b.num[i]%a*P,b.num[i]/=a;            b.num[0]/=a;            b.len=len;            while(b.len>1 && !b.num[b.len-1])b.len--;            return b;        }        void Rd(){            char A[L];            scanf("%s",A);            int SL=strlen(A);            len=0;            for(int i=SL-1,res;res=0,i>=0;num[len++]=res,i-=4){                if(i>=3)for(int j=i-3;j<=i;j++)res=(res<<1)+(res<<3)+(A[j]^48);                else for(int j=0;j<=i;j++)res=(res<<1)+(res<<3)+(A[j]^48);            }        }        void Pr(){            printf("%d",num[len-1]);            DREP(i,len-2,0)printf("%04d",num[i]);               }    }Ans,Sum,Tmp;    void Max(Big &a,Big b){        if(b.len>a.len)a=b;        else if(a.len==b.len){            if(a.num[a.len-1]<b.num[b.len-1])a=b;        }    }       void solve(){        Sum.Rd();        LL b;cin>>b;        REP(i,1,n)scanf("%d%d",&A[i].a,&A[i].b);        sort(A+1,A+1+n);        REP(i,1,n){            Tmp=Sum;            Tmp=Tmp/A[i].b;            Max(Ans,Tmp);            Sum=Sum*A[i].a;        }         Ans.Pr();    }}p100;int main(){//  freopen("game.in","r",stdin);//  freopen("game.out","w",stdout);    scanf("%d",&n);    if(n<=100)p60.solve();    else p100.solve();//  p100.solve();    return 0;}

drive ——4108

思路:预处理倍增,然后模拟,与暴力思路类似。(然而暴力又没敲T_T)

#include<bits/stdc++.h>#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)#define LL long long#define INF 0x3f3f3f3f #define N 100005#define T 20using namespace std;int n,m;int nxtb[N],nxta[N];struct p70{    int h[N];    void Init(){        REP(i,1,n-1){            int a=0,b=0,mn=INF;            REP(j,i+1,n){                int dx=abs(h[j]-h[i]);                if(dx<mn)mn=dx,a=j;                else if(dx==mn&&h[j]<h[a])a=j;            }            mn=INF;            REP(j,i+1,n){                if(j==a)continue;                int dx=abs(h[j]-h[i]);                if(dx<mn)mn=dx,b=j;                else if(dx==mn&&h[j]<h[b])b=j;            }            nxtb[i]=a;nxta[i]=b;        }    }    void solve(){        REP(i,1,n)scanf("%d",&h[i]);        int x0;cin>>x0;        Init();        int pos;        double mn=INF;        REP(i,1,n){            int f=1,beg=i,xi=x0;            LL l1=0ll,l2=0ll;            while(xi){                if(f){                    if(!nxta[beg])break;                    int dx=abs(h[beg]-h[nxta[beg]]);                    if(dx>xi)break;                    l1+=dx;xi-=dx;                    beg=nxta[beg];                    f=0;                }                 else {                    if(!nxtb[beg])break;                    if(abs(h[beg]-h[nxtb[beg]])>xi)break;                    l2+=abs(h[beg]-h[nxtb[beg]]);                    xi-=abs(h[beg]-h[nxtb[beg]]);                    beg=nxtb[beg];                    f=1;                }            }            double tmp;            if(!l2){                tmp=INF;                if(tmp<mn)mn=tmp,pos=i;                else if(tmp==mn&&h[i]>h[pos])pos=i;            }             else {                tmp=double(l1*1.0/l2);                if(tmp<mn)mn=tmp,pos=i;                else if(tmp==mn&&h[i]>h[pos])pos=i;            }        }        printf("%d\n",pos);        cin>>m;        REP(i,1,m) {            int beg,xi;            scanf("%d%d",&beg,&xi);            int f=1;            LL l1=0ll,l2=0ll;            while(xi){                if(f){                    if(!nxta[beg])break;                    int dx=abs(h[beg]-h[nxta[beg]]);                    if(dx>xi)break;                    l1+=dx;xi-=dx;                    beg=nxta[beg];                    f=0;                }                 else {                    if(!nxtb[beg])break;                    int dx=abs(h[beg]-h[nxtb[beg]]);                    if(dx>xi)break;                    l2+=dx;xi-=dx;                    beg=nxtb[beg];                    f=1;                }            }            printf("%lld %lld\n",l1,l2);        }       }}p70;LL fa[N][T],fb[N][T],f[N][T];struct node{    int h,id;    bool operator<(const node &a)const{        return h<a.h;    }}A[N];  set<node>S;set<node>::iterator it;struct car{    int id,dis;    bool operator<(const car &a)const{        if(dis==a.dis)return A[id].h<A[a.id].h;        else return dis<a.dis;    }}tmp[10];struct p100{    void Init(int i){        set<node>::iterator it=S.find(A[i]);        int cnt=0;        if(it!=S.begin()){            --it;            tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};            if(it!=S.begin()){                --it;                tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};                ++it;            }            ++it;        }        if((++it)!=S.end()){                tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};            if((++it)!=S.end())tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};        }        sort(tmp+1,tmp+1+cnt);        nxtb[i]=tmp[1].id;        if(cnt!=1)nxta[i]=tmp[2].id;    }    void work(int beg,int x,LL &l1,LL &l2){        DREP(j,T-1,0){            if(f[beg][j] && fa[beg][j]+fb[beg][j]<=x){                l1+=fa[beg][j],l2+=fb[beg][j];                x-=fa[beg][j]+fb[beg][j];                beg=f[beg][j];            }               }        int x1=nxta[beg];        if(!x1)return;        int d=abs(A[beg].h-A[x1].h);        if(d<=x)l1+=d;    }    void solve(){        REP(i,1,n)scanf("%d",&A[i].h),A[i].id=i;        S.insert(A[n]);        DREP(i,n-1,1)S.insert(A[i]),Init(i);        REP(i,1,n){            int x1=nxta[i],x2=nxtb[nxta[i]];            fa[i][0]=x1?abs(A[i].h-A[x1].h):0;            fb[i][0]=x2?abs(A[x1].h-A[x2].h):0;            f[i][0]=x2;        }        REP(j,1,T-1)            REP(i,1,n){                f[i][j]=f[f[i][j-1]][j-1];                fa[i][j]=fa[i][j-1]+fa[f[i][j-1]][j-1];                fb[i][j]=fb[i][j-1]+fb[f[i][j-1]][j-1];            }        int x0;        cin>>x0>>m;        LL ansa=1e18,ansb=0ll;        int pos=0;        REP(i,1,n){            LL l1=0ll,l2=0ll;            work(i,x0,l1,l2);            if (l2 && (!pos || l1*ansb<l2*ansa)){                ansa=l1;ansb=l2;                pos=i;            }        }        printf("%d\n",pos);        while(m--){            int beg,xi;            scanf("%d%d",&beg,&xi);            LL l1=0ll,l2=0ll;            work(beg,xi,l1,l2);            printf("%lld %lld\n",l1,l2);        }    }}p100;int main(){//  freopen("drive.in","r",stdin);//  freopen("drive.out","w",stdout);    cin>>n;    if(n<=1000)p70.solve();     else p100.solve();    return 0;}

小结:这次考试暴力又没敲,实则就是自己不会打,而且第2题切分又切错了T_T…

原创粉丝点击