[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 220000
#define inf 0x3ffffffffffffffLL
typedef long long ll;
int v[N],e[N],ne[N],nn,w[N];
void add(int x,int y,int z){
    ne[++nn]=e[x],e[x]=nn,v[nn]=y,w[nn]=z;
}
int n;
int dfn[N];

int tot;
int fa[N],ww[N*2],f2[N];
int bb,b1[N*2];
ll ss[N*2];
void dfs(int x){
    dfn[x]=++tot;
    for(int i=e[x];i;i=ne[i]){
        if(fa[x]==v[i])continue;
        if(!dfn[v[i]]){
            fa[v[i]]=x;
            f2[v[i]]=w[i];
            dfs(v[i]);
        }else{
            if(dfn[v[i]]>dfn[x]){
                for(int j=v[i];j!=x;j=fa[j]){
                    b1[++bb]=j;
                    ww[bb]=f2[j];
                }
                b1[++bb]=x;
                ww[bb]=w[i];
            }
        }
    }
}
int been[N];
ll dp1[N],dp2[N];
ll ans2;
int q1[N*2],he1,bo1;
int q2[N*2],he2,bo2;
ll v1[N*2],v2[N*2];
void dfs2(int x,int fa){
    for(int i=e[x];i;i=ne[i]){
        if(fa==v[i]||been[v[i]])continue;
        dfs2(v[i],x);
        ans2=max(ans2,dp1[x]+dp1[v[i]]+w[i]);
        dp1[x]=max(dp1[x],dp1[v[i]]+w[i]);
    }
}
ll ma;
void gg(int x,int y){
    if(q1[x]!=q2[y]){
      ma=max(ma,v1[x]+v2[y]);
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
        add(b,a,c);
    }
    dfs(1);
    for(int i=1;i<=bb;i++)been[b1[i]]=1;
    for(int i=1;i<=bb;i++){
        dfs2(b1[i],0);
    }
  for(int i=1;i<=bb;i++)ww[i+bb]=ww[i],b1[i+bb]=b1[i];
  for(int i=1;i<=bb*2;i++)ss[i]=ss[i-1]+(ll)ww[i];
   ll ans=inf;
   q1[he1=bo1=1]=1;
   q2[he2=bo2=1]=1;
   q1[++he1]=2;
   q2[++he2]=2;
   for(int i=3;i<=bb*2;i++){
       if(i-q1[bo1]>=bb)bo1++;
       if(i-q2[bo2]>=bb)bo2++;
       ma=0;
       while(he1>bo1+1&&v1[he1]>v1[he1-1]){
           swap(v1[he1],v1[he1-1]);
           swap(q1[he1],q1[he1-1]);
           he1--;
        }
       while(he2>bo2+1&&v2[he2]>v2[he2-1]){
          swap(v2[he2],v2[he2-1]);
          swap(q2[he2],q2[he2-1]);
          he2--;
        }
       q1[++he1]=i;
       q2[++he2]=i;
       v1[he1]=dp1[b1[i]]+ss[i-1];
       v2[he2]=dp1[b1[i]]-ss[i-1];
       if(i>bb){
          gg(bo1,bo2);
          gg(bo1,bo2+1);
          gg(bo1,he2);
          gg(bo1+1,bo2);
          gg(bo1+1,bo2+1);
          gg(bo1+1,he2);
          gg(he1,bo2);
          gg(he1,bo2+1);
          ans=min(ans,ma);
       }

    }
    ans=max(ans,ans2);
  if(ans%2LL==0LL){
       printf("%lld.0",ans/2LL);
    }else{
       printf("%lld.5",ans/2LL);
    }

 }

[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值,布布扣,bubuko.com

时间: 2024-12-28 02:03:09

[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值的相关文章

Hdu3401(dp+单调队列)

题目大意: 一个人有T元,最大可以持有的股票数量是maxp,交易必须隔w天进行.告诉每天可以买股票的数量和买入价格,以及每天可以卖出股票的数量和卖出价格,问最后最大的收益是多少. 思路: 状态可以定义为:f[i][j]第i天,手持j股且完成当天的操作的最大收益.考虑这一天的操作,一共有三种,(1)什么都不做,(2)在这一天,有一次卖出交易,(3)在这一天,有一次买入交易.那么也就是f[i][j]=max(f[i-1][j],f[i-w-1][k]+(j-k)*Bpi,f[i-w-1][k]-(k

【贪心/DP/单调队列】【CF1029B】Creating the Contest

Description 给你一个单调不下降的长度为n的序列,请你找出一个最长的子序列,满足找出的子序列中,\(A_i<=A_{i-1}~\times~2\),其中i为下标,A为找出的子序列.对于一个长度为\(p\)的子序列,\(i~\in~[1,p-1]\). Input 两行,第一行是原序列的长度\(n\) 第二行是\(n\)个数,代表原序列中的\(n\)个数. Output 一行一个数,代表最长的长度 Sample Input 10 1 2 5 6 7 10 21 23 24 49 Samp

习题:烽火传递(DP+单调队列)

烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确的传递,在m个烽火台中至少要有一个发出信号.现输入n.m和每个烽火台发出的信号的代价,请计算总共最少需要花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递!!![输入描述]第一行有两个数n,m(1<=n,m<=1000000)分别表示n个烽火台

P2627 修剪草坪[dp][单调队列]

P2627 修剪草坪 给你一个\(n\)个数字的数组,至多连续取\(k\)个数字,求取出的最大和. 预处理了前缀和之后,一维dp很容易想:\(dp[i] = max(dp[j-1] + sum[j+1,i])\) 用前缀和写就是\(dp[i]=max(dp[j-1]+sum[i]-sum[j])\) 把与\(i\)有关的拿出\(max\),就有\(dp[i]=sum[i]+max(dp[j-1]-sum[j])\) \(j\)能取的是一个固定区间,长度为\(k\),所以直接单调队列维护咯! 维护

【bzoj1040】[ZJOI2008]骑士 并查集+基环树dp

题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶

【BZOJ1915】[Usaco2010 Open]奶牛的跳格子游戏 DP+单调队列

[BZOJ1915][Usaco2010 Open]奶牛的跳格子游戏 Description 奶牛们正在回味童年,玩一个类似跳格子的游戏,在这个游戏里,奶牛们在草地上画了一行N个格子,(3 <=N <= 250,000),编号为1..N.就像任何一个好游戏一样,这样的跳格子游戏也有奖励!第i个格子标有一个数字V_i(-2,000,000,000 <=V_i <= 2,000,000,000)表示这个格子的钱.奶牛们想看看最后谁能得到最多的钱.规则很简单: * 每个奶牛从0号格子出发

[Vijos1617] 超级教主(DP + 单调队列)

传送门 设 f[i] 表示吃完 f[i] 及其以下的能量球后所剩下的能量. 所以 f[i] = max(f[i], f[j] + (sum[i] - sum[j]) - i * 100) ( 0 <= j < i ) 但这是 O(n2) 的,肯定超时, 把上面的式子变换以下得到 f[i] = max(f[i], (f[j] - sum[j]) + sum[i] - i * 100) ( 0 <= j < i ) 也就是说,f[i] 只与 f[j] - sum[j] 有关,sum[i

poj3017 dp+单调队列

http://poj.org/problem?id=3017 Description Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of

[BZOJ2442][Usaco2011 Open]修剪草坪 dp+单调队列优化

2442: [Usaco2011 Open]修剪草坪 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1118  Solved: 569[Submit][Status][Discuss] Description 在一年前赢得了小镇的最佳草坪比赛后,FJ变得很懒,再也没有修剪过草坪.现在,新一轮的最佳草坪比赛又开始了,FJ希望能够再次夺冠. 然而,FJ的草坪非常脏乱,因此,FJ只能够让他的奶牛来完成这项工作.FJ有N(1 <= N <= 100,0