题目描述
For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race using the T (2 ≤ T ≤ 100) cow trails throughout the pasture.
Each trail connects two different intersections (1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000), each of which is the termination for at least two trails. The cows know the lengthi of each trail (1 ≤ lengthi ≤ 1,000), the two intersections the trail connects, and they know that no two intersections are directly connected by two different trails. The trails form a structure known mathematically as a graph.
To run the relay, the N cows position themselves at various intersections (some intersections might have more than one cow). They must position themselves properly so that they can hand off the baton cow-by-cow and end up at the proper finishing place.
Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.
Each trail connects two different intersections (1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000), each of which is the termination for at least two trails. The cows know the lengthi of each trail (1 ≤ lengthi ≤ 1,000), the two intersections the trail connects, and they know that no two intersections are directly connected by two different trails. The trails form a structure known mathematically as a graph.
To run the relay, the N cows position themselves at various intersections (some intersections might have more than one cow). They must position themselves properly so that they can hand off the baton cow-by-cow and end up at the proper finishing place.
Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.
输入
* Line 1: Four space-separated integers: N, T, S, and E
* Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i
* Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i
输出
* Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.
样例输入
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
样例输出
10
所谓dfs序,就是把一棵树根据遍历的顺序压进一个序列里,这样我们就可以用线段树树状数组等各种骚操作搞它了。
我们dfs后 ,一棵树变成了一段序列。
然后对于每个节点,它的子树一定是一段连续的区间,那么问题就转化成了 给定一段区间,求区间不同数的个数加上剩余数不同数的个数,我们把序列延长一倍,就变成了统计两段连续区间内不同数的个数。树状数组瞎搞即可。
#include <bits/stdc++.h>
#define maxn 200005
using namespace std;
struct edges
{
int u,v,next;
}edge[maxn];
int head[maxn];
int cnt=0;
int n;
void addedge(int u,int v)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int sizes[maxn];
int in[maxn];//in表示遍历的时间戳
map<int,int> Mp;
int out[maxn];//出来的时间戳,那么子树大小(包括本身)就是out[i]-in[i]
bool vis[maxn];
int x=1;
void dfs(int num)//dfs序
{
for(int i=head[num];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(!vis[v])
{
vis[v]=true;
in[v]=x++;
Mp[x-1]=v;
dfs(v);
out[v]=x;
}
}
}
int ans[maxn];
int tree[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int pos,int val)
{
for(int i=pos;i<=n;i+=lowbit(i))
{
tree[i]+=val;
}
}
int sum(int x)
{
int res=0;
for(int i=x;i>0;i-=lowbit(i))
{
res+=tree[i];
}
return res;
}
struct quer
{
int l,r,id;
}query[maxn*2];
bool cmp(quer a,quer b)
{
return a.r<b.r;
}
int main()
{
int i;
//freopen("in.txt","r",stdin);
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(int i=2;i<=n;i++)
{ int v;
scanf("%d",&v);
addedge(i,v);
addedge(v,i);
}
vis[1]=true;
in[1]=x++;
Mp[1]=1;
dfs(1);
out[1]=x;
for(int i=1;i<=n;i++)
{
scanf("%d",&sizes[in[i]]);
}
for(int i=n+1;i<=2*n;i++)
{
sizes[i]=sizes[i-n];
}
n*=2;
int index=0;
for(int i=2;i<=n/2;i++)//这一步是在枚举每一棵树的子树,把它加到询问里。
{
int v=Mp[i];
int l=i;
int r=out[v]-1;
query[index].id=index;
query[index].l=l;
query[index++].r=r;
query[index].id=index;
query[index].l=r+1;
int tmp=n/2-(r-l+1);
query[index].r=query[index].l+tmp-1;
index++;
}
sort(query,query+index,cmp);
int cur=1;
Mp.clear();
for(int i=0;i<index;i++)//树状数组离线搞
{
for(int j=cur;j<=query[i].r;j++)
{
if(Mp[sizes[j]]!=0)
{
add(Mp[sizes[j]],-1);
}
add(j,1);
Mp[sizes[j]]=j;
}
cur=query[i].r+1;
ans[query[i].id]=sum(query[i].r)-sum(query[i].l-1);
}
int res=0;
for(int i=0;i<index;i+=2)
{
res=max(res,ans[i]+ans[i+1]);
}
printf("%d\n",res);
return 0;
}