贪心,递推,线段树,$RMQ$。

假设我们记$ans[i]$是以$i$点为起点对答案的贡献,那么答案就是$\sum\limits_{i = 1}^n {ans[i]}$。

$ans[i]$怎么计算呢?

首先,$[i+1,a[i]]$区间上肯定都是$1$(即上图紫线)。

然后在$[i+1,a[i]]$上找到一个$tmp$,使得$tmp$点能够达到的最右端是$[i+1,a[i]]$中最大的,那么$[a[i]+1,a[tmp]]$肯定都是2(即上图绿线)。

然后在$[a[i]+1,a[tmp]]$找一个$tmp2$......依次下去,计算出以$i$为起点对答案的贡献。

但是这样做复杂度太高,需要进行优化。

如果我们知道了$ans[tmp]$,那么就可以$O(1)$知道$ans[i]$,递推一下就可以了。

反过来想,如果我们想知道$ans[i]$,也就是要找到$tmp$,然后从$ans[tmp]$转移过来。

找$tmp$的话可以用线段树,也可以用$RMQ$预处理一下。

$RMQ$:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
char c=getchar(); x=;
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {x=x*+c-''; c=getchar();}
} const int maxn=;
int a[maxn],n,tmp,dp[maxn][];
LL ans[maxn]; void RMQ_init()
{
for(int i=;i<n;i++) dp[i][]=i;
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<n;i++){
if(a[dp[i][j-]]>a[dp[i+(<<(j-))][j-]]) dp[i][j]=dp[i][j-];
else dp[i][j]=dp[i+(<<(j-))][j-];
}
} int RMQ(int L,int R)
{
int k=;
while((<<(k+))<=R-L+) k++;
if(a[dp[L][k]]>a[dp[R-(<<k)+][k]]) return dp[L][k];
return dp[R-(<<k)+][k];
} int main()
{
scanf("%d",&n);
for(int i=;i<n-;i++) scanf("%d",&a[i]),a[i]--;
a[n-]=n-; RMQ_init(); ans[n-]=; LL d=;
for(int i=n-;i>=;i--)
{
tmp=RMQ(i+,a[i]);
ans[i]=ans[tmp]-(a[i]-tmp)+n--a[i]+a[i]-i;
d=d+ans[i];
}
printf("%lld\n",d);
return ;
}

线段树:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
char c=getchar(); x=;
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {x=x*+c-''; c=getchar();}
} const int maxn=;
int a[maxn],n,s[*maxn],M,tmp;
LL ans[maxn]; void build(int l,int r,int rt)
{
if(l==r) { s[rt]=a[l]; return; }
int m=(l+r)/; build(l,m,*rt); build(m+,r,*rt+);
s[rt]=max(s[*rt],s[*rt+]);
} void f(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) { M=max(M,s[rt]); return; }
int m=(l+r)/;
if(L<=m) f(L,R,l,m,*rt);
if(R>m) f(L,R,m+,r,*rt+);
} void force(int l,int r,int rt)
{
if(l==r) {tmp=l; return;}
int m=(l+r)/;
if(s[*rt]==M) force(l,m,*rt);
else force(m+,r,*rt+);
} void h(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(s[rt]<M) return;
force(l,r,rt); return;
}
int m=(l+r)/;
if(L<=m) h(L,R,l,m,*rt); if(tmp!=-) return;
if(R>m) h(L,R,m+,r,*rt+); if(tmp!=-) return;
} int main()
{
scanf("%d",&n);
for(int i=;i<=n-;i++) scanf("%d",&a[i]); a[n]=n;
build(,n,); ans[n]=; LL d=;
for(int i=n-;i>=;i--)
{
M=tmp=-; f(i+,a[i],,n,); h(i+,a[i],,n,);
ans[i]=ans[tmp]-(a[i]-tmp)+n-a[i]+a[i]-i;
d=d+ans[i];
}
printf("%lld\n",d);
return ;
}

CodeForces 675E Trains and Statistic的更多相关文章

  1. Codeforces 675E Trains and Statistic - 线段树 - 动态规划

    题目传送门 快速的vjudge通道 快速的Codeforces通道 题目大意 有$n$个火车站,第$i$个火车站出售第$i + 1$到第$a_{i}$个火车站的车票,特殊地,第$n$个火车站不出售车票 ...

  2. Codeforces 675E Trains and Statistic(DP + 贪心 + 线段树)

    题目大概说有n(<=10W)个车站,每个车站i卖到车站i+1...a[i]的票,p[i][j]表示从车站i到车站j所需买的最少车票数,求所有的p[i][j](i<j)的和. 好难,不会写. ...

  3. codeforces 675E Trains and Statistic 线段树+贪心统计

    分析:这个题刚看起来无从下手 但是我们可以先简化问题,首先可以固定起点i,求出i+1到n的最小距离 它可以到达的范围是[i+1,a[i]],贪心的想,我们希望换一次车可以到达的距离尽量远 即:找一个k ...

  4. codeforces E. Trains and Statistic(线段树+dp)

    题目链接:http://codeforces.com/contest/675/problem/E 题意:你可以从第 i 个车站到 [i + 1, a[i]] 之间的车站花一张票.p[i][j]表示从 ...

  5. CF 675E Trains and Statistic

    草稿和一些题解而已 因为指针太恶心了 所以query决定还是要试试自己yy一下 #include<cstdio> #include<cstring> #include<i ...

  6. codeforces 675E E. Trains and Statistic(线段树+dp)

    题目链接: E. Trains and Statistic time limit per test 2 seconds memory limit per test 256 megabytes inpu ...

  7. Codeforces Round #353 (Div. 2) E. Trains and Statistic dp 贪心

    E. Trains and Statistic 题目连接: http://www.codeforces.com/contest/675/problem/E Description Vasya comm ...

  8. 【34.54%】【codeforces 675E】Trains and Statistic

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  9. Codeforces Round #353 (Div. 2) E. Trains and Statistic 线段树+dp

    题目链接: http://www.codeforces.com/contest/675/problem/E 题意: 对于第i个站,它与i+1到a[i]的站有路相连,先在求所有站点i到站点j的最短距离之 ...

随机推荐

  1. NotePad++安装和配置C/C++开发插件

    NotePad++ - 安装和配置C/C++开发插件 | NotePad++ - Install and Configure plugins for develop C/C++ http://aofe ...

  2. CSS盒子的浮动

    web前端学习笔记(CSS盒子的浮动) 在标准流中,一个块级元素在水平方向会自动伸展,直到包含它的元素的边界:而在竖直方向和兄弟元素依次排列,不能并排.使用“浮动”方式后,块级元素的表现就会有所不同. ...

  3. jquery选择器之属性过滤选择器

    <style type="text/css"> /*高亮显示*/ .highlight{ background-color: gray } </style> ...

  4. K2 BPM项目 基于COM组件调用SAP RFC 问题

    K2 BPM项目 基于COM组件调用SAP RFC 问题 问题前景: 环境:Win 2008 R2 64bit 最近项目中有支流程需求中需要在会计入账环节回写SAP的会计凭证. SAP组给我们提供.N ...

  5. Fast Token Replacement in C#

    http://www.codeproject.com/Articles/298519/Fast-Token-Replacement-in-Csharp Fast Token Replacement i ...

  6. 去除scons构建动态库的前缀lib

    如何使用scons构建工程,请参考快速构建C++项目工具Scons,结合Editplus搭建开发环境. 编译SharedLibrary项目的时候,生产的so文件时自动加上lib, 例如: env = ...

  7. 从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响

    首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...

  8. [置顶] 遵循Java EE标准体系的开源GIS服务平台之二:平台部署

    传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...

  9. Android本地化资源目录详解

    我们可以设想,有两个不同分辨率的手机(320*480和480*800)要使用一些图像资源,为了使图像不失真,就需要为不同分辨率的手机指定不同的图像,为此就需要建立不同的资源目录. 在res目录中建立了 ...

  10. html标签详解,html标签属性大全(完美版),包括css属性详解

    这个是平时放在笔记里,需要什么了,查下当字典用,想不起来了就查下,个人在用有道云,查询框一输就找到了.下篇会把我整理手机的html5发了.引用在某处常看到的话.楼主耗时费心整理··请拿走······· ...