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待补
还是很有收获吧,同时也感受到了差距,,