其他分享
首页 > 其他分享> > 2020.11.1 校测解题报告

2020.11.1 校测解题报告

作者:互联网

2020.11.1 校测


十一月份的第一次校测就这么没了qaq。。。


这T1,T2不是水题么??NM为啥会爆炸


T1

铺设道路

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
#define ll long long
#define InF 0x7fffffff
#define Max 10e5
#define Min -10e5
using namespace std;
/*==========================================快读*/
int read()
{
    int x=0,f=1;
	char c=getchar();
    while(c<'0'||c>'9')
	{
		if(c=='-') 
			f=-1;
		c=getchar();
	}
    while(c>='0'&&c<='9')
    { 
		x=(x<<3)+(x<<1)+(c^48); 
		c=getchar();
	}
    return x*f;
} 
/*======================================定义变量*/
int n,d[100010],ans;
/*====================================自定义函数*/

/*========================================主程序*/
int main()
{
  	n=read();
  	for(int i=1;i<=n;i++)
  	{
  		d[i]=read();
  		if(d[i]>d[i-1])
  			ans+=d[i]-d[i-1];
	  }
	printf("%d",ans);
	return 0;
}

T2

货币系统

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
/*====================================快读*/
int read() {
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-')
			f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9') {
		x=(x<<3)+(x<<1)+(c^48);
		c=getchar();
	}
	return x*f;
}
/*======================================定义变量*/
int T;
int n,a[30030];
bool f[30030];
int ans;
/*====================================自定义函数*/
//bool su(int a)
//{
//	for(int i=2;i<=sqrt(a);i++)
//		if(a%i==0)
//			return false;
//	return true;
//}
/*========================================主程序*/
int main() {
//	freopen("money.in","r",stdin);
//	freopen("money.out","w",stdout);
	T=read();
	while(T--) {
		ans=0;
		memset(f,false,sizeof(f));
		n=read();
		for(int i=1; i<=n; i++)
			a[i]=read();
		sort(a+1,a+n+1);
		f[a[1]]=false;
		for(int i=1; i<=n; i++)
		{
			if(f[a[i]]) continue;
			ans++;//
			f[a[i]]=true;//
			for(int j=a[i]+1;j<=a[n];j++) //
				f[j]=f[j]|f[j-a[i]];
		}
//		for(int i=1;i<=n;i++)
//			if(!f[a[i]])
		printf("%d\n",ans);
	}
	return 0;
}


T3

赛道修建

你的任务是设计一种赛道修建的方案,使得修建的 m 条赛道中长度最小的赛道长度最大(即 m 条赛道中最短赛道的长度尽可能大)

长度最小的最大?二分?!根据题意寻找使最小的赛道长度最大的决策方案,题目就转化为了在一棵树上寻找 \(m\) 条小于等于 \(k\) 的路径。

二分那个修建的 \(m\) 条赛道中长度最小的赛道的长度 \(k\) (求树上最长路详见 吕sir 的双dfs法和树上DP法),然后判断 。

如何判断?对于每个结点,把所有传上来的值 \(val\) 放进一个 \(multiset\) ,其实这些值对答案有贡献就两种情况:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
#define ll long long
#define InF 0x7fffffff
#define Max 10e5
#define Min -10e5
using namespace std;
/*==========================================快读*/
inline int read()
{
    register int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
    	if(ch=='-')
        f=-1;
       ch=getchar();
     }
    while(isdigit(ch))
    {
    	x=(x<<3)+(x<<1)+ch-'0';
      ch=getchar();
     }
    return (f==1)?x:-x;
}
/*======================================定义变量*/
const int maxn=50000+10;
int n,m,head[maxn],tot,ans,up;
struct node{
    int to,next,val;
}e[maxn<<1];
multiset<int> s[maxn];
multiset<int>::iterator it;
/*====================================自定义函数*/
inline void add(int x,int y,int w)
{
    e[++tot].to=y;
    e[tot].val=w;
    e[tot].next=head[x];
    head[x]=tot;
}
int dfs(int x,int fa,int k)
{
    s[x].clear();
    int val;
    for(int i=head[x],y;i;i=e[i].next){
        y=e[i].to;
        if(y==fa)
        	continue;
        val=dfs(y,x,k)+e[i].val;
        if(val>=k)
        	ans++;
        else 
           s[x].insert(val);
    }
    int Max=0;
    while(!s[x].empty())
    {
        if(s[x].size()==1)
        	return max(Max,*s[x].begin());
        it=s[x].lower_bound(k-*s[x].begin());
        if(it==s[x].begin()&&s[x].count(*it)==1)
        	it++;
        if(it==s[x].end())
        {
            Max=max(Max,*s[x].begin());
            s[x].erase(s[x].find(*s[x].begin()));
        }
        else 
        {
            ans++;
            s[x].erase(s[x].find(*it));
            s[x].erase(s[x].find(*s[x].begin()));
        }
    }
    return Max;
}
int check(int k)
{
    ans=0;
    dfs(1,0,k);
    if(ans>=m)
    	return 1;
    return 0;
}
int dfs1(int x,int fa)
{
    int sum1=0,sum2=0;
    for(int i=head[x],y;i;i=e[i].next)
    {
        y=e[i].to;
        if(y==fa)
        	continue;
        sum2=max(sum2,dfs1(y,x)+e[i].val);
        if(sum1<sum2)
        	swap(sum1,sum2);
    }
    up=max(up,sum1+sum2);
    return sum1;
}
/*========================================主程序*/
int main()
{
    n=read(),m=read();
    int x,y,w;
    for(int i=1;i<n;i++)
    {
        x=read(),y=read(),w=read();
        add(x,y,w);
        add(y,x,w);
    }
    dfs1(1,0);
    int l=1,r=up,mid;
    while(l<r)
    {
        mid=l+r+1>>1;
        if(check(mid)) 
        	l=mid;
        else
        	r=mid-1;
    }
    printf("%d\n",l);
    return 0;
}

总结:

着实不甘心。

线性 \(DP\) ,树上 \(DP\) ,差分,树上最长路,\(and\) \(so\) \(on\) 。

标签:赛道,val,int,校测,while,解题,2020.11,include,define
来源: https://www.cnblogs.com/Frather/p/14003268.html