[TJOI2014]Alice and Bob

题目描述:

定义一个序列 x1,x2...xn x 1 , x 2 . . . x n
a序列 a1,a2...an a 1 , a 2 . . . a n 表示以i为结尾的最长上升子序列的长度
b序列 b1,b2...bn b 1 , b 2 . . . b n 表示以i为开头的最长下降子序列的长度
求在满足a序列的情况下 Max(ni=1bi) M a x ( ∑ i = 1 n b i )

题目分析:

根据求LIS的方法,我们可以知道
ai a i 不为1,则存在一个 aj=ai1 a j = a i − 1
如果多个 ai a i 相同,那么我们尽量让后面的数小比较好
那么构造的方法就出来了
设定last[i]为 val=ai v a l = a i 出现的最后位置,我们从 last[ai1]>i l a s t [ a i − 1 ] − > i 然后DFS,由于后加入的点在链表中的访问比先加入的点早,那么就满足了第二个条件,我们跑一边构造出的树,求出dfn即可
然后用树状数组求解答案

题目链接:

Luogu 3971
BZOJ 5158

Ac 代码:

#include 
#include 
#include 
#define lowbit(x) (x&(-x))
const int maxm=1e5+100;
int num[maxm],tot;
int head[maxm],to[maxm<<1],net[maxm<<1],cnt;
int last[maxm],b[maxm],c[maxm];
int n;
inline void addedge(int u,int v)
{
    to[++cnt]=v,net[cnt]=head[u],head[u]=cnt;
}
void dfs(int now)
{
    b[now]=tot++;
    for(int i=head[now];i;i=net[i]) dfs(to[i]);
}
inline void ins(int x,int val)
{
    for(int i=x;i<=maxm;i+=lowbit(i))
     c[i]=std::max(c[i],val);
}
inline int ask(int x)
{
    int res=0;
    for(int i=x;i;i-=lowbit(i))
     res=std::max(res,c[i]);
    return res;
}
int main()
{
    scanf("%d",&n);
    last[0]=n+1;
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        addedge(last[x-1],i);
        last[x]=i;
    }
    dfs(n+1);
    long long ans=0;
    for(int i=n;i>=1;i--)
    {
        int poi=ask(b[i]-1)+1;
        ans+=(long long)poi;
        ins(b[i],poi);
    }
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(题目分析,DFS,贪心)