CodeForces 675E Trains and Statistic

贪心,递推,线段树,$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-6;
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=0;
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) {x=x*10+c-‘0‘; c=getchar();}
}

const int maxn=100010;
int a[maxn],n,tmp,dp[maxn][30];
LL ans[maxn];

void RMQ_init()
{
    for(int i=0;i<n;i++) dp[i][0]=i;
    for(int j=1;(1<<j)<=n;j++)
        for(int i=0;i+(1<<j)-1<n;i++){
            if(a[dp[i][j-1]]>a[dp[i+(1<<(j-1))][j-1]]) dp[i][j]=dp[i][j-1];
            else dp[i][j]=dp[i+(1<<(j-1))][j-1];
        }
}

int RMQ(int L,int R)
{
    int k=0;
    while((1<<(k+1))<=R-L+1) k++;
    if(a[dp[L][k]]>a[dp[R-(1<<k)+1][k]]) return dp[L][k];
    return dp[R-(1<<k)+1][k];
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n-1;i++) scanf("%d",&a[i]),a[i]--;
    a[n-1]=n-1; RMQ_init(); ans[n-1]=0; LL d=0;
    for(int i=n-2;i>=0;i--)
    {
        tmp=RMQ(i+1,a[i]);
        ans[i]=ans[tmp]-(a[i]-tmp)+n-1-a[i]+a[i]-i;
        d=d+ans[i];
    }
    printf("%lld\n",d);
    return 0;
}

线段树:

#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-6;
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=0;
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) {x=x*10+c-‘0‘; c=getchar();}
}

const int maxn=100010;
int a[maxn],n,s[4*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)/2; build(l,m,2*rt); build(m+1,r,2*rt+1);
    s[rt]=max(s[2*rt],s[2*rt+1]);
}

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)/2;
    if(L<=m) f(L,R,l,m,2*rt);
    if(R>m) f(L,R,m+1,r,2*rt+1);
}

void force(int l,int r,int rt)
{
    if(l==r) {tmp=l; return;}
    int m=(l+r)/2;
    if(s[2*rt]==M) force(l,m,2*rt);
    else force(m+1,r,2*rt+1);
}

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)/2;
    if(L<=m) h(L,R,l,m,2*rt); if(tmp!=-1) return;
    if(R>m) h(L,R,m+1,r,2*rt+1); if(tmp!=-1) return;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++) scanf("%d",&a[i]); a[n]=n;
    build(1,n,1); ans[n]=0; LL d=0;
    for(int i=n-1;i>=1;i--)
    {
        M=tmp=-1; f(i+1,a[i],1,n,1); h(i+1,a[i],1,n,1);
        ans[i]=ans[tmp]-(a[i]-tmp)+n-a[i]+a[i]-i;
        d=d+ans[i];
    }
    printf("%lld\n",d);
    return 0;
}
时间: 2024-11-10 07:33:19

CodeForces 675E Trains and Statistic的相关文章

【CF675E】Trains and Statistic(贪心,DP,线段树优化)

题意:a[i]表示从第i个车站可以一张票到第[i+1,a[i]]这些车站;p[i][j]表示从第i个车站到第j个车站的最少的票数,现在要求∑dp[i][j](1<=i<=n,i<j<=n); 思路:从I开始走,在i+1到a[i]之间一定会到使a[j]最大的j,因为要使步数最小,接下来能走得更快 区间询问最值用RMQ与线段树都可以 dp[i]表示dp[i,i+1],dp[i,i+2]...dp[i,n]这些值的和 dp[i]=dp[k]+(n-i)-(a[i]-k),k为[i+1,a

Codeforces675E Trains and Statistic RMQ优化 dp+贪心

题意: a[i]表示从第i个车站买一张票可以坐到第[i+1,a[i]]个车站中任一个p[i][j]表示从第i个车站到第j个车站的最少的票数,求∑p[i][j](1<=i<=n,i<j<=n) 思路: 构造dp[i]=∑p[i][j](i<j≤n) 贪心的想,每次从第i个车站买票坐到第m个车站(在[i+1,a[i]]中,a[m]最大),再往后坐车的选择是最优的,因为每次都能使在买相同的票数下走的最远.除非目的地是在[i+1,a[i]]这个区间内,不需要走得远. 这样就可以分类讨

Codeforces Round #353 (Div. 2) ABCDE 题解 python

Problems # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring Painting standard input/output 1 s, 256 MB    x2519 C Money Transfers standard input/output 1 s, 256 MB    x724 D Tree Construction standard input/output 2

[合集]国庆休闲补题

Hrbust - 1846 题意:序列每个格子允许放O和X,求长度为n的序列中至少存放m个连续的O的方案数 容斥+dp 设\(dp[i]\)为长度为\(i\)时的合法方案数 转移的个数来自于上一个状态的合法序列后面接上O和X,既\(dp[i-1]*2\) 也有可能来自于本来不合法的方案,转移后就合法了,那先固定一部分状态,因为转移后才合法,所以假定序列中[i-m+1,i]全部为O,那么前面就可以为所欲为,有\(2^{i-m}\)个状态,但\(2^{i-m}\)中会有合法方案的存在,因此需要减去已

Codeforces Round #325 (Div. 2)D. Phillip and Trains BFS

                                             D. Phillip and Trains The mobile application store has a new game called "Subway Roller". The protagonist of the game Philip is located in one end of the tunnel and wants to get out of the other one.

codeforces Gym 100338H High Speed Trains

递推就好了,用二项式定理算出所有连边的方案数,减去不合法的方案, 每次选出一个孤立点,那么对应方案数就是上次的答案. 枚举选几个孤立点和选哪些,选到n-1个点的时候相当于都不选,只减1. 要用到高精度,直接开100*100的组合数数组会MLE,用滚动数组优化一下就好了. 不会java,python太伤了 #include<bits/stdc++.h> using namespace std; const int MAXN = 20000; struct bign { int len, s[MA

Codeforces Round #416

(?_?)最近脑子不好使(虽然一直都不太好用...) A题换了三个思路,全wa了(ó﹏ò?),改了差不多15遍都有了(菜的醉死...) 最后让老大给我看看,哇,错了好多地方???????. 大佬给我改好了代码,我自己又开始改,我的小宇宙要爆发了,还好最后也改对了(菜的要撞墙了 |墙|????:)); CodeForces - 811A A. Vladik and Courtesy time limit per test 2 seconds memory limit per test 256 me

Acdream 1420 High Speed Trains(大数 + 容斥原理)

传送门 High Speed Trains Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statistic Next Problem Problem Description The kingdom of Flatland has n cities. Recently the king of Flatland visited Japan and was amazed

CF586D. Phillip and Trains

1 /* 2 CF586D. Phillip and Trains 3 http://codeforces.com/problemset/problem/586/D 4 搜索 5 */ 6 #include<cstdio> 7 #include<algorithm> 8 #include<string.h> 9 using namespace std; 10 const int Nmax=110; 11 char map[4][Nmax]; 12 int fail[4]