AcCoders 10699:多校B层冲刺NOIP20221015城市游历 题解
30pts
针对 \(n \le 100\) 的数据,暴力对每个询问的接受程度跑一遍,时间复杂度 \(O(n^3)\)。
70pts
显然,在 MST 上走最优。
针对 \(l_i,r_i,k_i \le 10^5\) 的数据,考虑预处理接受程度为 \(i\) 时能去的不同种类的景点数 \(f_i\),答案为 \(\sum^r_{i=l}f_i\),前缀和计算即可。
100pts
70pts 的算法为什么仍然无法满分?因为题目中 \(l_i,r_i,k_i \le 10^9\),存不下。
OJ 的奇妙特性:数组开小 RE,数组开略大一点 MLE,再大 RE,最大 CE,其中后三种都会导致爆零。
那么我们必须换一种存储方法。
看到 \(c_i \le 600\),不难想到离散化记录每个转折点,计算答案的时候再判断即可。
考虑 \(f_i\) 的统计方式,从起点开始遍历整棵树,记录下起点 \(s\) 到每个点 \(v\) 路程中的最大困难系数 \(k\),走困难系数小于 \(k\) 的边就不会出现与 \(c_v\) 相同的特征值,则 \(k\) 为转折点之一,将 \(f_k+1\)。
//10699 Problem C:多校B层冲刺NOIP20221015城市游历
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int MAXN=500005;
struct Edge{int u,v,w;}s[500005];
struct TreeNode{int to,w;};
int n,m,q,x,op,mod,c[MAXN],fa[MAXN],mn[605],sum[605],mp[605];
ll ans;
vector<TreeNode> g[MAXN];
int find(int x){return (x==fa[x]?x:fa[x]=find(fa[x]));}
void DFS(int u,int f,int mx)
{
mn[c[u]]=min(mn[c[u]],mx);
for(TreeNode v:g[u])
{
if(v.to==f)
continue;
DFS(v.to,u,max(mx,v.w));
}
return;
}
void kruskal()
{
int x,y;
sort(s+1,s+m+1,[](Edge a,Edge b){return a.w<b.w;});
for(int i=1;i<=m;i++)
{
x=find(s[i].u);
y=find(s[i].v);
if(x==y)
continue;
g[s[i].u].push_back({s[i].v,s[i].w});
g[s[i].v].push_back({s[i].u,s[i].w});
fa[x]=y;
}
return;
}
int main()
{
freopen("tour.in","r",stdin);
freopen("tour.out","w",stdout);
int l,r;
scanf("%d%d%d%d",&n,&m,&q,&x);
memset(mp,0x7f,sizeof(mp));
memset(mn,0x7f,sizeof(mn));
for(int i=1;i<=n;i++)
{
scanf("%d",c+i);
fa[i]=i;
}
for(int i=1;i<=m;i++)
scanf("%d%d%d",&s[i].u,&s[i].v,&s[i].w);
kruskal();
DFS(x,0,0);
sort(mn+1,mn+601);
for(int i=1;i<=600;i++)
{
if(mn[i]>=1e9)
break;
sum[i]++;
mp[i]=mn[i];
}
for(int i=1;i<=600;i++)
sum[i]+=sum[i-1];
while(q--)
{
scanf("%d%d",&l,&r);
if(l>r)
swap(l,r);
ans=0;
for(int i=1;i<=600;i++)
{
if(mp[i+1]>=l&&mp[i]<l)
ans+=1ll*(min(mp[i+1],r+1)-l)*sum[i];
if(mp[i]>=l&&mp[i]<=r)
ans+=1ll*(min(mp[i+1],r+1)-mp[i])*sum[i];
}
printf("%lld\n",ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}
/*
* AcCoders-2022NOIPB层联测510月15日
* http://www.accoders.com/problem.php?cid=4235&pid=2
* -std=c++23 -Wall -fno-ms-extensions
* 2022.10.18
*/
并查集不加路径压缩会 TLE 30,别问我怎么知道的。

浙公网安备 33010602011771号