10.25~10.30任务题

来源:互联网 发布:java流程引擎框架 编辑:程序博客网 时间:2024/04/28 05:35

三道11年noip。

vijos1738,1740,1741

1738

地址:https://vijos.org/p/1738

做法:做法:没有做法,就是暴力大法师,一道代码题,打打下落、消除这些基本操作。数组从0开始写比1好写,真是神奇。

代码如下:

#include <bits/stdc++.h>#define M 30using namespace std;int n,m,i,j,t,k,y,tp,showski;int a[M][M],cnt[M],f[M][M],ans[M][M],mo[3]={0,1,-1};inline void ps(int aa[M][M],int bb[M][M],int cc[],int dd[]){    for(int i=0;i<5;i++)        for(int j=0;j<7;j++) aa[i][j]=bb[i][j];    for(i=1;i<=t;i++) cc[i]=dd[i];}inline int ok(){    int tt=0;for(int i=1;i<=t;i++)        if(cnt[i]) if(!tt||tt>cnt[i])            tt=cnt[i];return tt;}inline void fl(int x){    for(int i=0,j;i<7;i++)        if(a[x][i]==0){            for(j=i+1;j<7&&a[x][j]==0;j++);            if(j==7) return;            else a[x][i]=a[x][j],a[x][j]=0;        }}inline int C(){    int ff=0;for(int i=0;i<5;i++)        for(int j=0;j<7;j++){            if(!a[i][j]) continue;            if(i<3&&a[i][j]==a[i+1][j]&&a[i][j]==a[i+2][j])                f[i][j]=f[i+1][j]=f[i+2][j]=1;            if(j<5&&a[i][j]==a[i][j+1]&&a[i][j]==a[i][j+2])                f[i][j]=f[i][j+1]=f[i][j+2]=1;        }for(i=0;i<5;i++) for(j=0;a[i][j]&&j<7;j++)            if(f[i][j]) ff=1,cnt[a[i][j]]--,a[i][j]=f[i][j]=0;    for(i=0;i<5;i++) fl(i);return ff;}inline void dfs(int x){    int b[M][M],c[M];ps(b,a,c,cnt);    for(int i=0;i<5;i++) for(int j=0;a[i][j]&&j<7;j++)        for(int k=1;k<=2;k++)            if(i+mo[k]>=0&&i+mo[k]<5){                if((mo[k]==-1&&a[i-1][j])||a[i][j]==a[i+mo[k]][j]) continue;                ans[x][1]=i;ans[x][2]=j;ans[x][3]=mo[k];                swap(a[i][j],a[i+mo[k]][j]);                for(fl(i),fl(i+mo[k]);C(););tp=ok();                if(x==n) if(tp==0)                for(i=showski=1;i<=n;i++)                    printf("%d %d %d\n",ans[i][1],ans[i][2],ans[i][3]);                if(showski==1) return;                if(x!=n&&tp>2) dfs(x+1);                ps(a,b,cnt,c);             }}int main(){    for(scanf("%d",&n),i=0;i<5;i++)        for(j=0;j<=7;j++){             scanf("%d",&y);if(y==0) break;            a[i][j]=y;t=t>y?t:y;cnt[y]++;        }dfs(1);if(!showski) printf("-1\n");return 0;}

1740

地址:https://vijos.org/p/1740

做法:如果你手算几个(或者你比较聪明的话),你应该就可以看出来检验值Yi是单调的,所以一眼二分。1s的时间,nlogn就过了,不写树状数组了。

代码如下:

#include <bits/stdc++.h>#define M 200010#define ll long longusing namespace std;ll n,m,s,i,j,x,y,a,b,t,ans;ll v[M],w[M],l[M],r[M],sum[M],cnt[M];inline ll cal(ll x){    for(t=cnt[0]=sum[0]=0,i=1;i<=n;i++){        sum[i]=sum[i-1];cnt[i]=cnt[i-1];        if(w[i]>=x) cnt[i]++,sum[i]+=v[i];    }for(i=0;i<m;i++)        t+=(cnt[r[i]]-cnt[l[i]-1])*(sum[r[i]]-sum[l[i]-1]);    return t;}int main(){    for(scanf("%lld%lld%lld",&n,&m,&s),i=1;i<=n;i++){        scanf("%lld%lld",&w[i],&v[i]);        if(a>w[i]) a=w[i];        if(b<w[i]) b=w[i];    }for(i=0;i<m;i++)        scanf("%lld%lld",&l[i],&r[i]);    while(b-a>1){        ll mid=a+b>>1;        if(cal(mid)>s) a=mid;else b=mid;    }ans=min(abs(cal(a)-s),abs(cal(b)-s));    printf("%lld\n",ans);return 0;}

1741

地址:https://vijos.org/p/1741

做法:想到了一个极其暴力的贪心,看到vijos标签上写树形动规只觉得汗颜。只要存下车开到每个站点的时间和该站点最晚到的乘客的时间。每次寻找一段路,使得坐车的人最多,并且满足车比下一个站点最晚到的乘客到的晚,然后使劲用加速器。如果加速器太多了,直到车和最晚到的乘客同时到达下一个站点即可,然后寻找下一个合法的区间。最后扫一遍统计答案就好了。

#include <bits/stdc++.h>#define M 100010using namespace std;int showski=1,n,m,k,i,j,mx,xx,ans; int t[M],a[M],b[M],ar[M],la[M],d[M],tmp[M],sum[M];int main(){    for(scanf("%d%d%d",&n,&m,&k),i=1;i<n;i++) scanf("%d",&d[i]);    for(i=1;i<=m;i++){        scanf("%d%d%d",&t[i],&a[i],&b[i]);        sum[b[i]]++;        if(t[i]>la[a[i]]) la[a[i]]=t[i];    }for(i=2;i<=n;i++) sum[i]+=sum[i-1];    while(showski){        for(ar[1]=0,i=2;i<=n;i++) ar[i]=max(ar[i-1],la[i-1])+d[i-1];        for(tmp[n]=n,i=n-1;i>=1;i--){            tmp[i]=tmp[i+1];            if(ar[i+1]<=la[i+1]) tmp[i]=i+1;         }for(mx=1;!d[mx]&&mx<=n-1;) mx++;        if(mx==n||k==0) break;        for(i=mx+1;i<n;i++)            if(d[i]&&sum[tmp[mx]]-sum[mx]<sum[tmp[i]]-sum[i]) mx=i;        if(sum[tmp[mx]]-sum[mx]==0) break;        for(xx=M-5,i=mx+1;i<=tmp[mx]-1;i++)            xx=min(xx,ar[i]-la[i]);        xx=min(xx,k);xx=min(xx,d[mx]);k-=xx;d[mx]-=xx;        //cout<<k<<" "<<xx<<endl;system("pause");    }for(i=1;i<=m;i++) ans+=abs(ar[b[i]]-t[i]);    printf("%d\n",ans);return 0;}
0 0
原创粉丝点击