NOIP2018

Day1

T1 Road

贪心:差分

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define Maxn 100100
int n,ans;
int a[Maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i]>a[i-1])ans+=a[i]-a[i-1];
    }
    printf("%d",ans);
    return 0;
}

T2 Money

完全背包

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
#define Maxn 110
#define R register
int n,T;
int tot=0;
int f[25100]={};
int a[Maxn];
int b[Maxn];
bool cmp(int x,int y){return x<y;}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
    tot=0;
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(f,0,sizeof(f));
    scanf("%d",&n);
    for(R int i=1;i<=n;i++)scanf("%d",&a[i]);
    sort(a+1,a+n+1,cmp);
    f[0]=1;
    for(R int i=1;i<=n;i++)
    {
        for(R int j=1;j<=tot;j++)
        {
            for(R int k=a[i-1];k<=a[i];k++)
                f[k]+=f[k-b[j]];
        }
        if(f[a[i]]==0)
        {
            b[++tot]=a[i];
        }
    }
    printf("%d\n",tot);
    }
    return 0;
}

T3 Track

这道题考察了对于dp状态的设计(当一些dp状态不好设计的时候,不如直接按题目要求设计)

以及从小数据入手,再到大数据的思想

不会用容器,但学到了很巧妙的设初值的方法,代码实现较难

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define Maxn 500100
#define R register
int n,m;
int fir[Maxn],nxt[Maxn*2],vv[Maxn*2],edge[Maxn*2];
int tot=0;
int ans=0;
int s[Maxn],tag[Maxn],dp[Maxn];
void add(int x,int y,int z)
{
    nxt[++tot]=fir[x];
    fir[x]=tot;
    vv[tot]=y;
    edge[tot]=z;
}
void dfs(int u,int fa,int x)
{
    int cnt=0;
    for(R int i=fir[u];i;i=nxt[i])
    {
        int v=vv[i];
        if(v==fa)continue;
        dfs(v,u,x);
    }
    for(R int i=fir[u];i;i=nxt[i])
    {
        int v=vv[i];
        if(v==fa)continue;
        s[++cnt]=dp[v]+edge[i];
    }
    int maxx=0;int num=0;
    sort(s+1,s+cnt+1);
    for(R int i=cnt;i>=1&&s[i]>=x;i--)cnt--,ans++;
    for(R int i=1;i<=cnt;i++)
    {
        if(tag[i]!=u)
        {
            int l=i+1,r=cnt,tmp=cnt+1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(s[i]+s[mid]>=x)
                    tmp=mid,r=mid-1;
                else l=mid+1;
            }
            while(tag[tmp]==u&&tmp<=cnt)tmp++;
            if(tmp<=cnt)
            {
                tag[i]=u;tag[tmp]=u;ans++;
            }
        }
    }
    for(R int i=cnt;i>=1;i--)
    {
        if(tag[i]!=u)
        {
            dp[u]=s[i];break;
        }
    }
    return;
}
int check(int x)
{
    ans=0;
    dfs(1,0,x);
    if(ans>=m)return 1;else return 0;
}
int main()
{
    scanf("%d%d",&n,&m);
    int c=0;
    for(R int i=1;i<n;i++)
    {
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);c+=z;
    }
    int l=0,r=c/m;
    int anss=0;
    while(l<=r)
    {
        memset(dp,0,sizeof(dp));
        memset(tag,0,sizeof(tag));
        int mid=(l+r)>>1;
        if(check(mid)==1)
        {
            anss=mid;l=mid+1;
        }
        else r=mid-1;
    }
    printf("%d\n",anss);
    return 0;
}

Day 2

T1 Travel

很朴素的基环树

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define Maxn 5010
#define R register
int n,m;
int fir[Maxn],nxt[Maxn*2],vv[Maxn*2];
int tot=0;
int rt1,rt2;
int num=0;
int fa[Maxn],vis[Maxn]={},circle[Maxn],cnt=0,found=0;
void add(int x,int y)
{
    nxt[++tot]=fir[x];
    fir[x]=tot;
    vv[tot]=y;
}
int s[Maxn][Maxn],tail[Maxn],ans1[Maxn],ans2[Maxn];
void dfs1(int u,int fa)
{
    printf("%d ",u);
    for(R int i=1;i<=tail[u];i++)
    {
        if(s[u][i]==fa)continue;
        dfs1(s[u][i],u);
    }
    return;
}
void dfs2(int u,int fa)
{
    ans2[++num]=u;
    for(R int i=1;i<=tail[u];i++)
    {
        int v=s[u][i];
        if((s[u][i]==fa)||(u==rt1&&v==rt2)||(u==rt2&&v==rt1))continue;
        dfs2(s[u][i],u);
    }
    return;
}
void find_curcle(int u,int F)
{
    fa[u]=F;
    vis[u]=1;
    for(R int i=fir[u];i;i=nxt[i])
    {
        int v=vv[i];
        if(v==F)
        {
            F=-1;
            continue;
        }
        if(!vis[v])find_curcle(v,u);
        else
        {
            found=1;
            circle[cnt=1]=u;
            int tmp=u;
            do
            {
                tmp=fa[tmp];
                circle[++cnt]=tmp;
            }while(tmp!=v);
            return;
        }
        if(found==1)return;
    }
}
void solve()
{
    circle[cnt+1]=circle[1];
    memset(ans1,0x3f3f3f3f,sizeof(ans1));
    for(R int i=1;i<=cnt;i++)
    {
        rt1=circle[i];rt2=circle[i+1];
        int pd=0;num=0;
        dfs2(1,0);
        for(R int j=1;j<=n;j++)
        {
            if(pd!=0)break;
            for(R int k=1;k<=n;k++)
            {
                if(ans2[k]<ans1[k]){pd=2;break;}
                if(ans2[k]>ans1[k]){pd=1;break;}
            }
        }
        if(pd==2)
        {
            for(int j=1;j<=n;j++)ans1[j]=ans2[j];
        }
    }
}
int main()
{
  //  freopen("travel.in","r",stdin);
   // freopen("travel.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(R int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        tail[x]++;tail[y]++;
        s[x][tail[x]]=y;s[y][tail[y]]=x;
        add(x,y);add(y,x);
    }
    int a[Maxn];
    for(R int i=1;i<=n;i++)
    {
        for(R int j=1;j<=tail[i];j++)
        {
            a[j]=s[i][j];
        }
        sort(a+1,a+tail[i]+1);
        for(R int j=1;j<=tail[i];j++)s[i][j]=a[j];
    }
   if(m==n-1)
        dfs1(1,0);
    else
    {
        find_curcle(1,0);
        solve();
    for(R int i=1;i<=n;i++)printf("%d ",ans1[i]);
    }
    return 0;
}

T2、T3待补

还是很有收获吧,同时也感受到了差距,,

posted @ 2019-08-03 21:30  Akaina  阅读(192)  评论(0编辑  收藏  举报