您的位置:首页 > 其它

bzoj3242: [Noi2013]快餐店 树形dp+线段树

2015-07-13 12:21 351 查看
对于不是环上的点我们可以用树形dp解决,剩下的就是在一个环上找距离最远的两点。我们可以拆环,几下每个点第一大和第二大的距离

这样最长链就是max{sum[j]-sum[i]+dis[i]+dis[j]}。

于是用两颗线段树分别维护max{sum[j]+dis[j]}和max{dis[i]-sum[i]}。然后更新答案。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define ss printf("fuck\n");
#define oo 200000000000000LL;
#define sint long long
#define maxn 300100
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define getmid int mid=(l+r)>>1
int read()
{
int res;char c;
while(c=getchar(),c<'0'||c>'9');
res=c-'0';
while(c=getchar(),c>='0'&&c<='9')
res=res*10+c-'0';
return res;
}
sint sum[maxn],f[maxn],dis[maxn];
sint max1[maxn*4],max2[maxn*4],val[maxn];
sint max21[maxn*4],max22[maxn*4];
int n,label1[maxn*4],label2[maxn*4];
int label21[maxn*4],label22[maxn*4];
int next[maxn],first[maxn],to[maxn],en;
sint ans=-oo;
void print1(int x,int l,int r)
{
printf("%d %d %d %d %d %lld %lld\n",x,l,r,label1[x],label2[x],max1[x],max2[x]);
}
void print2(int x,int l,int r)
{
printf("%d %d %d %d %d %lld %lld\n",x,l,r,label21[x],label22[x],max21[x],max22[x]);
}
void add(int a,int b,sint c)
{
en++;
to[en]=b;val[en]=c;
next[en]=first[a];
first[a]=en;
}
int cir1[maxn],tot,ed;
bool vis[maxn];
bool dfs(int now,int last)
{
//printf("%d %d\n",now,last);
//system("pause");
vis[now]=1;
for(int i=first[now];i;i=next[i])
{
int v=to[i];
if(v==last) continue;
if(vis[v])
{
tot++;ed=v;
cir1[tot]=now;
return true;
}
if(dfs(v,now))
{
tot++;
cir1[tot]=now;
if(now!=ed)
{
return true;
}
else
{
return false;
}
}
}
vis[now]=false;
return false;
}
void dfs2(int x,int last)
{
sint maxl=0;
for(int i=first[x];i;i=next[i])
{
int v=to[i];
if(vis[v]||v==last) continue;
dfs2(v,x);
if(f[v]+val[i]>=f[x])
{
maxl=f[x];
f[x]=f[v]+val[i];
}
else
{
maxl=max(maxl,f[v]+val[i]);
}
}
ans=max(ans,f[x]+maxl);
}
void pushup1(int rt)
{
if(max1[rt<<1]>max1[rt<<1|1])
{
label1[rt]=label1[rt<<1];
max1[rt]=max1[rt<<1];
if(max2[rt<<1]>max1[rt<<1|1])
{
label2[rt]=label2[rt<<1];
max2[rt]=max2[rt<<1];
}
else
{
label2[rt]=label1[rt<<1|1];
max2[rt]=max1[rt<<1|1];
}
}
else if(max1[rt<<1]==max1[rt<<1|1])
{
label1[rt]=label1[rt<<1];
label2[rt]=label1[rt<<1|1];
max2[rt]=max1[rt]=max1[rt<<1];
}
else
{
label1[rt]=label1[rt<<1|1];
max1[rt]=max1[rt<<1|1];
if(max2[rt<<1|1]>max1[rt<<1])
{
label2[rt]=label2[rt<<1|1];
max2[rt]=max2[rt<<1|1];
}
else
{
label2[rt]=label1[rt<<1];
max2[rt]=max1[rt<<1];
}
}
}
void build1(int l,int r,int rt)
{
if(l==r)
{
max1[rt]=dis[l]+sum[l];
max2[rt]=-oo;
label1[rt]=cir1[l];
//print1(rt,l,r);
return;
}
getmid;
build1(lson);
build1(rson);
pushup1(rt);
//print1(rt,l,r);
}
void pushup2(int rt)
{
if(max21[rt<<1]>max21[rt<<1|1])
{
label21[rt]=label21[rt<<1];
max21[rt]=max21[rt<<1];
if(max22[rt<<1]>max21[rt<<1|1])
{
label22[rt]=label22[rt<<1];
max22[rt]=max22[rt<<1];
}
else
{
label22[rt]=label21[rt<<1|1];
max22[rt]=max21[rt<<1|1];
}
}
else if(max21[rt<<1]==max21[rt<<1|1])
{
label21[rt]=label21[rt<<1];
label22[rt]=label21[rt<<1|1];
max22[rt]=max21[rt]=max21[rt<<1];
}
else
{
label21[rt]=label21[rt<<1|1];
max21[rt]=max21[rt<<1|1];
if(max22[rt<<1|1]>max21[rt<<1])
{
label22[rt]=label22[rt<<1|1];
max22[rt]=max22[rt<<1|1];
}
else
{
label22[rt]=label21[rt<<1];
max22[rt]=max21[rt<<1];
}
}
}
void build2(int l,int r,int rt)
{
if(l==r)
{
max21[rt]=dis[l]-sum[l];
max22[rt]=-oo;
label21[rt]=cir1[l];
return;
}
getmid;
build2(lson);
build2(rson);
pushup2(rt);
//print2(rt,l,r);
}
struct node
{
int num;
sint val;
void cl()
{
num=0;val=-oo;
}
};
bool operator < (node aa,node bb)
{
if(aa.val!=bb.val) return aa.val<bb.val;
return aa.num<bb.num;
}
node query1(int l,int r,int rt,int x,int y)
{
if(x<=l&&r<=y)
{
node tmp;
tmp.val=max1[rt];
tmp.num=label1[rt];
return tmp;
}
getmid;
node t1,t2;
t1.cl();t2.cl();
if(x<=mid) t1=query1(lson,x,y);
if(y>mid) t2=query1(rson,x,y);
if(t1<t2) swap(t1,t2);
return t1;
}
node query2(int l,int r,int rt,int x,int y)
{
if(x<=l&&r<=y)
{
node tmp;
tmp.val=max2[rt];
tmp.num=label2[rt];
return tmp;
}
getmid;
node t1,t2;
t1.cl();t2.cl();
if(x<=mid) t1=query2(lson,x,y);
if(y>mid) t2=query2(rson,x,y);
if(t1.val<t2.val) swap(t1,t2);
return t1;
}
node query21(int l,int r,int rt,int x,int y)
{
if(x<=l&&r<=y)
{
node tmp;
tmp.val=max21[rt];
tmp.num=label21[rt];
return tmp;
}
getmid;
node t1,t2;
t1.cl();t2.cl();
if(x<=mid) t1=query21(lson,x,y);
if(y>mid) t2=query21(rson,x,y);
if(t1<t2) swap(t1,t2);
return t1;
}
node query22(int l,int r,int rt,int x,int y)
{
if(x<=l&&r<=y)
{
node tmp;
tmp.val=max22[rt];
tmp.num=label22[rt];
return tmp;
}
getmid;
node t1,t2;
t1.cl();t2.cl();
if(x<=mid) t1=query22(lson,x,y);
if(y>mid) t2=query22(rson,x,y);
if(t1<t2) swap(t1,t2);
return t1;
}
sint solve(int x)
{
node tmp1=query1(1,tot*2,1,x,x+tot-1);
node tmp2=query2(1,tot*2,1,x,x+tot-1);
node tmp21=query21(1,tot*2,1,x,x+tot-1);
node tmp22=query22(1,tot*2,1,x,x+tot-1);
sint v=-oo;
if(tmp1.num!=tmp21.num)
v=max(v,tmp1.val+tmp21.val);
if(tmp1.num!=tmp22.num)
v=max(v,tmp1.val+tmp22.val);
if(tmp2.num!=tmp21.num)
v=max(v,tmp2.val+tmp21.val);
if(tmp2.num!=tmp22.num)
v=max(v,tmp2.val+tmp22.val);
return v;
}
int main()
{

scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int a,b;
sint c;
a=read();b=read();c=read();

add(a,b,c);
add(b,a,c);
}
//printf("orz1");
dfs(1,0);
//printf("orz1");
memset(vis,0,sizeof(vis));
for(int i=1;i<=tot;i++)
{
vis[cir1[i]]=1;
}
for(int i=1;i<=tot;i++)
{
dfs2(cir1[i],0);
}
for(int i=1;i<=tot;i++)
{
dis[i]=f[cir1[i]];
}
for(int i=1;i<=tot;i++)
{
cir1[i+tot]=cir1[i];
dis[i+tot]=dis[i];
}
for(int i=2;i<=tot*2;i++)
{
for(int j=first[cir1[i]];j;j=next[j])
{
if(to[j]==cir1[i-1])
{
sum[i]=sum[i-1]+val[j];
break;
}
}
}
build1(1,tot*2,1);
build2(1,tot*2,1);

sint ans2=oo;
for(int i=1;i<=tot+1;i++)
{
ans2=min(ans2,solve(i));
}
ans=max(ans,ans2);
printf("%.1lf",double(ans)/2);

return 0;
}
/*
4
1 2 1
1 4 2
1 3 2
2 4 1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: