AGC 030B.Tree Burning(贪心)

题目链接


\(Description\)

有一个长为\(L\)的环,上面有\(n\)棵树,坐标分别为\(a_i\)。初始时在原点。
每次你可以选择顺时针或逆时针走到第一棵没有被烧掉的树,停在这个位置,然后烧掉这棵树。重复这一过程直到所有树都被烧掉。
求走的总路程最多可以是多少。
\(n\leq2\times10^5,\ a_i,L\leq10^9\)。

\(Solution\)

真的菜啊QAQ 当时连这个都不会

记顺时针走一次为\(L\),逆时针走一次为\(R\)。
初步想法是\(LRLRLR...\)这样走。但显然有反例(比如两棵树分别在\(1,\ L-1\))。
事实上用\(LLLLRLR...\)和\(RRRLRLR...\),这两种走法就没问题了。(具体证明没有大概既然开始来回走了,就比继续往一个方向走更优吧?
前缀和后缀和预处理一下,枚举刚开始反复横跳进行\(LRLR...\)的位置就可以了。


//8ms   4608KB
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 500000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=2e5+5;

int A[N];
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
    int now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-48,c=gc());
    return now;
}
LL Solve(const int n,const int L)
{
    static LL pre[N],suf[N];
    for(int i=1; i<=n; ++i) pre[i]=pre[i-1]+A[i];
    for(int i=n; i; --i) suf[i]=suf[i+1]+L-A[i];
    LL ans=A[n];
    for(int i=1,p; i<n; ++i)
        p=i+((n-i)>>1), (n-i)&1 ? ans=std::max(ans,(suf[p+2]+pre[p]-pre[i]+A[i])*2+L-A[p+1]) : ans=std::max(ans,(suf[p+1]+pre[p-1]-pre[i]+A[i])*2+A[p]);
    return ans;
}

int main()
{
    const int L=read(),n=read();
    for(int i=1; i<=n; ++i) A[i]=read();
    LL ans=Solve(n,L);
    std::reverse(A+1,A+1+n);
    for(int i=1; i<=n; ++i) A[i]=L-A[i];
    ans=std::max(ans,Solve(n,L));
    printf("%lld\n",ans);

    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/10346849.html

时间: 2024-11-08 20:27:47

AGC 030B.Tree Burning(贪心)的相关文章

AGC 030 B - Tree Burning

B - Tree Burning 链接 题意: 一个长度为L的环,有n个位置上有树,从0出发,每次选择一个方向(顺时针或者逆时针),一直走,直到走到一棵树的位置,烧掉这棵树,重复这个过程,直到没有树.求最多走多少距离. 分析: 最优一定是LLLRLRLRL……类似这样的,于是枚举每个点,计算答案. 代码: 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream

hdu4912 Paths on the tree --- LCA贪心

给一棵n个结点的树,m条路径的起点和终点, 问至多可以选择多少条路径使其两两间没有公共点. 这题的主要问题是, 1.如何判断两条路径上没有交点 2.按什么策略来选 看上去感觉是最大匹配问题,但nm的范围较大问题1无法高效的解决. 画个图发现可能和LCA有关,但比赛时不知道这到底有什么用,完全没想贪心. 要选择尽量多,就是要尽量避免冲突. 我们选择一个点作为根,把给的边画出来建树就可以发现,尽量选深度大的路径可以使冲突尽量小. 于是把路径按LCA深度由大到小排序,依次和之前不冲突就可以选. 下面就

HDU--4786 Fibonacci Tree 生成树+贪心?

N个顶点,M条边,每条边可能为黑色或是白色( 0 or 1 ),问有没有可能用为斐波那契数的数目的白色边构成一棵生成树.所以需要删掉图中的环,根据每次删掉的边有一个白色边的上限和下限,判断一下中间有没有斐波那契数就可以了.实现方法是根据颜色排序,先放黑色边得到的是最小数目的白色边构成的生成树,先放白色边得到是最大数目的白色边构成的生成树. #include<cstring> #include<string> #include<fstream> #include<i

AGC 030 B - Tree Burning 结论+枚举

考试 T2,是一个脑筋急转弯. 最暴力的贪心是每次先选左,再选右,再选左..... 然而这么做在一些情况下是错的. 但是,我们发现我们的选法一定是 $LLLLRLRLRLRLR$ 或 $RRRRLRLRLRLRLR$ (易证明) 所以直接枚举第一次向左/右走多少次,然后剩余的直接 $O(1)$ 计算即可. 原文地址:https://www.cnblogs.com/guangheli/p/11809014.html

hdu 1055 &amp; poj 2054 Color a Tree 树&amp;贪心 找最大费用点和父节点合并

Color a Tree Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7144 Accepted: 2458 Description Bob is very interested in the data structure of a tree. A tree is a directed graph in which a special node is singled out, called the "root"

Codeforces 196C Paint Tree(贪心+极角排序)

题目链接 Paint Tree 给你一棵n个点的树和n个直角坐标系上的点,现在要把树上的n个点映射到直角坐标系的n个点中,要求是除了在顶点处不能有线段的相交. 我们先选一个在直角坐标系中的最左下角的点,把根结点放到这个点中,然后对剩下的点进行极角排序,按逆时顺序一个个塞进来,类似地递归处理. 这样就满足了题意. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b

Codeforces 963B Destruction of a Tree 【贪心】

本题的贪心策略是:每次删除连到叶子结点的dfs链上离根最远的偶数度的结点 greed is good 实现方法是先维护一个degree[i]表示第i个点有多少个度,然后dfs,当每一个结点的所有子节点被访问后准备返回时判断当前结点degree的奇偶性,如果是偶数就删除,是奇数就什么都不做.这样能保证你删除的结点[的子孙]度数都是奇数,及保证删除了[离根最远的偶数度的结点].每次删除要把它父亲和son的degree都减1,并且如果son的degree减完以后是偶数的话就把son也删除.(以为这样能

CF 1039D You Are Given a Tree &amp;&amp; CF1059E Split the Tree 的贪心解法

1039D 题意: 给你一棵树,要求对给定链长于 k = 1, 2, 3, ..., n,求出最大的链剖分. 1059E 题意: 给你一棵带权树,要求对于一组给定的 L, W 求出最小完全竖链剖分满足每条链点数不超过 L,权值和不超过 W. 显然两题是有共同点的,就是让我们求满足一定条件的树的最值链剖分. 比较暴力的可以尝试用 DP 计数,但是我不想深入 DP,因为方程比较复杂,思考起来不太容易. 很巧的是,这两题可以用相似的贪心思想来做. 在思考具体细节之前,需要明确贪心的主要思想:在从下往上

[CSP-S模拟测试]:Tree(贪心)

题目描述 给定一颗$n$个点的树,树边带权,试求一个排列$P$,使下式的值最大 $$\sum \limits_{i=1}^{n-1}maxflow(P_i,P_{i+1})$$ 其中$maxflow(s,t)$表示从点$s$到点$t$之间的最大流,即从$s$到$t$的路径上最小的边权 输入格式 第一行一个整数$n$,表示点数下接$n−1$行,每行三个数$u,v,w$表示一条连接点$u$和点$v$权值为$w$的边 输出格式 输出一行一个整数,表示答案 样例 样例输入: 21 2 2333 样例输出