[CCF] 201503-5 最小花费
题目:
思路:
思路是LCA求出路径,然后再贪心,价钱最低的时候把后面需要的粮食都卖了
只得了30分
我觉得肯定是tle了,应该不会RE,它数据量太大了,离线处理想不到什么好办法,
在线处理的话我觉得就是找LCA,求出路径再贪心。
LCA可以O1, 求路径就On了,再加个sort,妥妥地TLE
我的30分代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
const int maxm = 2e5+20;
struct Edge{
int to,Next;
}edge[maxm];
int head[maxn],tot;
int n;
int price[maxn];
int dfn[maxn*2];
int deep[maxn*2];
int father[maxn];
int Fir[maxn];
int cnt;
int Min[maxn*2][23];
int suffixSum[maxn];
int Log2[maxn*2]={-1};
int num[maxn];
int downFirstLess[maxn];
int upFirstLess[maxn];
void DFS(int u,int fa)
{
for(int i=head[u];i!=-1;i=edge[i].Next)
{
int v = edge[i].to;
if(price[v])
}
}
vector<int> route,Dis;
bool cmp(int,int);
int LCA (int,int);
void RMQ();
void dfs(int,int,int);
void initEdge();
void addedge(int,int);
int main()
{
int u,v,d,m;
cin>>n>>m;
map<pair<int,int>,int> mp;
initEdge();
for(int i=1;i<=n;++i)
scanf("%d",price+i);
for(int i=1;i<n;++i)
{
scanf("%d%d%d",&u,&v,&d);
addedge(u,v);
addedge(v,u);
mp[make_pair(u,v)] = d;
mp[make_pair(v,u)] = d;
}
cnt = 0;
dfs(1,1,1);
RMQ();
while(m--)
{
scanf("%d%d",&u,&v);
int lca = LCA(u,v);
route.clear();
Dis.clear();
while(true)
{
route.push_back(u);
if(u==lca) break;
u = father[u];
}
stack<int> st;
while(v!=lca)
{
st.push(v);
v = father[v];
}
while(!st.empty())
{
route.push_back(st.top());
st.pop();
}
int len = route.size();
for(int i=0;i<len-1;++i)
Dis.push_back(mp[make_pair(route[i],route[i+1])]);
for(int i=0;i<len;++i)
num[i] = route[i];
sort(num,num+len,cmp);
map<int,int> PointToDfn;
for(int i=0;i<len;++i)
{
PointToDfn[route[i]] = i;
}
suffixSum[len-1] = 0;
for(int i=len-2;i>=0;--i)
suffixSum[i] = suffixSum[i+1]+Dis[i];
int Left = len-1;
long long res = 0;
for(int i=0;i<len;++i)
{
int node = num[i];
int pos = PointToDfn[node];
if(pos<Left)
{
res += 1ll*price[node]*(suffixSum[pos]-suffixSum[Left]);
Left = pos;
if(pos==0) break;
}
}
printf("%lld\n",res);
}
return 0;
}
void RMQ()
{
int N = n*2-1;
for(int i=1;i<=N;++i)
Min[i][0] = i, Log2[i] = Log2[i/2]+1;
for(int j=1;(1<<j)<=N;++j)
{
for(int i=1;i+(1<<j)-1<=N;++i)
{
int a = Min[i][j-1];
int b = Min[i+(1<<(j-1))][j-1];
Min[i][j] = deep[a]>deep[b]?b:a;
}
}
}
int LCA (int u,int v)
{
int x = Fir[u], y = Fir[v];
if(x>y) swap(x,y);
int j = Log2[y-x+1];
int a = Min[x][j], b = Min[y-(1<<j)+1][j];
return deep[a]>deep[b]?dfn[b]:dfn[a];
}
void initEdge()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int from,int to)
{
edge[tot].to = to;
edge[tot].Next = head[from];
head[from] = tot++;
}
void dfs(int u,int fa,int dep)
{
father[u] = fa;
dfn[++cnt] = u;
deep[cnt] = dep;
Fir[u] = cnt;
for(int i=head[u];i!=-1;i=edge[i].Next)
{
int v = edge[i].to;
if(v==fa) continue;
dfs(v,u,dep+1);
dfn[++cnt] = u;
deep[cnt] = dep;
}
}
bool cmp(int x,int y)
{
return price[x]<price[y];
}
感谢wyt学姐提供的思路
日后有空再实现这个思路吧~