本场题解于8月1日晚上九点回忆时所写,尽可能还原答题时代码,两个题均是100%通过。
笔试题第一题:给定上课的开始时间和结束时间,求需要几个人可以把这些课完整的都上完。
把开始时间和结束时间点拆开 结束时间是-1 开始时间是1 然后sort排序 按节点大小排序 然后节点一样的 把-1的放前面 然后就变成前缀和最大值问题了
#include<bits/stdc++.h>
using namespace std;
const int maxn=4e5+200;
struct node{
int x,y;
}a[maxn];
bool cmp(node a, node b){
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[2*i].x=x;
a[2*i].y=1;
a[2*i+1].x=y;
a[2*i+1].y=-1;
}
sort(a, a+2*n, cmp);
int ans=0,tmp=0;
for(int i=0;i<2*n;i++){
tmp+=a[i].y;
ans=max(ans, tmp);
}
printf("%d\n", ans);
return 0;
}
笔试第二题:给定一棵树,求一条连续链上的节点和最大值,这里的链指的是任意子树的根结点到该子树的任意节点。即该链不需要从根结点开始,也不需要在叶子节点结束,但是方向必须是向下的(只能是父节点到子节点)。
构建树之后,然后贪心选择子树连续值大于0的加进来即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+200;
const int mod=1e9+3;
long long val[maxn], new_val[maxn];
long long ans;
vector<int>g[maxn];
void dfs(int u){
new_val[u]=val[u];
long long tmp=0;
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
dfs(v);
if(new_val[v]>0)tmp+=new_val[v];
}
if(tmp>0)new_val[u]+=tmp;
ans=max(ans, new_val[u]);
}
int main(){
int n;
scanf("%d",&n);
int root;
for(int i=0;i<n;i++){
long long x;
int y;
scanf("%lld%d",&x,&y);
if(y==0)root=i;
else g[y-2].push_back(i);
val[i]=x;
}
ans=val[root];
dfs(root);
printf("%lld\n", ans%mod);
return 0;
}