【NOIP2017】Day1

题目传送门(请点击开头目录)
http://blog.csdn.net/lhq_er/article/details/76693851

Solution

T1:排完序后贪心比较
T2:dp[t][i][j]表示t时间能否一个为一个为j,转移方程很好写。
T3:
30%:建图后最小生成树
100%:Kruskal慢在最所有边排序,其实很多边权值是相同的,所以对行列单独排序,再取,取的时候要注意去重,不多说了

CODE

//T1;
#include
#include
#include
using namespace std;
#define ll long long
const int MAXN=50005;
int a[MAXN],b[MAXN];
bool flag[MAXN*2];
int n,m;

int main()
{
    freopen("cards.in","r",stdin);
    freopen("cards.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        flag[a[i]]=true;
    }   
    for (int i=1;i<=n+n;i++)
        if (!flag[i]) b[++m]=i;
    sort(a+1,a+1+n);
    sort(b+1,b+1+m);
    int j=n,i=0;
    for (i=n;i>=1;i--)
    {
        while (j>=1 && a[j]>b[i]) j--;
        if (j<1) break;
        j--;
    }
    printf("%d\n",n-i); 
    return 0;
}
//T2;
#include
#include
#include
using namespace std;
#define ll long long
const int MAXN=105;
int n,m,d,t,ans=0x3f3f3f3f;
bool f[MAXN][MAXN][MAXN];

int main()
{
    freopen("cups.in","r",stdin);
    freopen("cups.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&t,&d);
    f[0][0][0]=true;
    for (int i=0;ifor (int j=0;j<=n;j++)
            for (int k=0;k<=m;k++)
            {
                if (!f[i][j][k]) continue;
                f[i+1][0][k]=true;
                f[i+1][j][0]=true;
                f[i+1][n][k]=true;
                f[i+1][j][m]=true;
                if (j>=m-k) f[i+1][j-(m-k)][m]=true;
                else f[i+1][0][k+j]=true;
                if (k>=n-j) f[i+1][n][m-(n-j)]=true;
                else f[i+1][j+k][0]=true;               
            }
    for (int j=0;j<=n;j++)
        for (int k=0;k<=m;k++)
            if (f[t][j][k])
                ans=min(ans,abs(j+k-d));
    printf("%d\n",ans); 
    return 0;
}
//T3;
#include
#include
#include
using namespace std;
#define ll long long
const int MAXN=50005;
ll x[MAXN],y[MAXN],row[MAXN],col[MAXN],num[2];
ll A,B,n,m,ans=0,last=0,cnt;


struct node{
    ll v,k;
}d[MAXN];
bool cmp(const node &x,const node &y)
{
    if (x.v!=y.v) return x.v<y.v;
    return x.k<y.k;
}
int main()
{
    freopen("spicychicken.in","r",stdin);
    freopen("spicychicken.out","w",stdout);
    scanf("%lld%lld%lld%lld",&A,&B,&n,&m);
    for (ll i=1;i<=n;i++)
        scanf("%lld",&x[i]);
    for (ll j=1;j<=m;j++)
        scanf("%lld",&y[j]);
    x[n+1]=A; y[m+1]=B;
    sort(x+1,x+1+n);
    sort(y+1,y+1+m);
    for (ll i=0;i<=n;i++)
        row[i]=x[i+1]-x[i],d[i].v=row[i],d[i].k=0;
    for (ll j=0;j<=m;j++)
        col[j]=y[j+1]-y[j],d[j+n+1].v=col[j],d[j+n+1].k=1;
    sort(d,d+n+m+2,cmp);
    cnt=(n+1)*(m+1)-1;
    for (ll i=0;im+2 && cnt;i++)
    {
        if (!num[0] || !num[1])
        {
            if (d[i].k==0) ans+=m*d[i].v,cnt-=m,num[0]++;
            else ans+=n*d[i].v,cnt-=n,num[1]++;
            continue;
        }
        if (d[i].k==0) ans+=(m-num[1]+1)*d[i].v,cnt-=m-num[1]+1,num[0]++;
        else ans+=(n-num[0]+1)*d[i].v,cnt-=n-num[0]+1,num[1]++;
        last=d[i].v;
    }
    if (cnt<0) ans-=last*abs(cnt);
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(竞赛—NOIP2017模拟赛,题解,宁波)