zoukankan      html  css  js  c++  java
  • CF1132G Greedy Subsequences

    题目链接:洛谷

    题目大意:对于一个长度为$n$的序列$a_i$,它的最长贪心严格上升子序列定义为(1)最长上升子序列(2)对于这个子序列,每个数的后继必须是在原序列中它右边第一个比它大的数。求所有长度为$k$的子区间中,它的最长贪心严格上升子序列的长度。

    数据范围:$1leq kleq nleq 10^6,1leq a_ileq n$


    我们注意到每个数的后继是唯一的,所以可以在数列后面加上一个$n+1$,然后它就是一个树结构。

    然后直接用一个单调栈就可以建出来这棵树了。

    那么这个最长贪心严格上升子序列的长度就是这个树上的最长链(只能从儿子到父亲)

    如果在这个子区间内增加一个$a[x]$,那就是以$x$这个点的子树内的点为起点的最长贪心严格上升子序列都加上1,删除就是减去1。

    就用一个线段树维护区间加,区间$max$就可以了。

     1 #include<bits/stdc++.h>
     2 #define Rint register int
     3 using namespace std;
     4 const int N = 1000003;
     5 int n, k, p[N], stk[N], top, head[N], to[N], nxt[N], dfn[N], siz[N], tim;
     6 inline void add(int a, int b){
     7     static int cnt = 0;
     8     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
     9 }
    10 inline void dfs(int x){
    11     dfn[x] = ++ tim; siz[x] = 1;
    12     for(Rint i = head[x];i;i = nxt[i]) dfs(to[i]), siz[x] += siz[to[i]];
    13 }
    14 int seg[N << 2], lazy[N << 2];
    15 inline void pushdown(int x){
    16     if(lazy[x]){
    17         seg[x << 1] += lazy[x];
    18         seg[x << 1 | 1] += lazy[x];
    19         lazy[x << 1] += lazy[x];
    20         lazy[x << 1 | 1] += lazy[x];
    21         lazy[x] = 0;
    22     }
    23 }
    24 inline void pushup(int x){seg[x] = max(seg[x << 1], seg[x << 1 | 1]);}
    25 inline void change(int x, int L, int R, int l, int r, int v){
    26     if(l <= L && R <= r){
    27         seg[x] += v; lazy[x] += v;
    28         return;
    29     }
    30     int mid = L + R >> 1;
    31     pushdown(x);
    32     if(l <= mid) change(x << 1, L, mid, l, r, v);
    33     if(mid < r) change(x << 1 | 1, mid + 1, R, l, r, v);
    34     pushup(x);
    35 }
    36 int main(){
    37     scanf("%d%d", &n, &k);
    38     for(Rint i = 1;i <= n;i ++) scanf("%d", p + i);
    39     for(Rint i = 1;i <= n;i ++){
    40         while(top && p[stk[top]] < p[i]){
    41             add(i, stk[top]); -- top;
    42         }
    43         stk[++ top] = i;
    44     }
    45     while(top) add(n + 1, stk[top]), -- top;
    46     dfs(n + 1);
    47     for(Rint i = 1;i <= k;i ++) change(1, 1, n + 1, dfn[i], dfn[i] + siz[i] - 1, 1);
    48     printf("%d", seg[1]);
    49     for(Rint i = k + 1;i <= n;i ++){
    50         change(1, 1, n + 1, dfn[i], dfn[i] + siz[i] - 1, 1);
    51         change(1, 1, n + 1, dfn[i - k], dfn[i - k] + siz[i - k] - 1, -1);
    52         printf(" %d", seg[1]);
    53     }
    54 }
    View Code
  • 相关阅读:
    21. Merge Two Sorted Lists
    496. Next Greater Element I
    (转载)深度学习的weight initialization
    Python collections模块
    Iterables vs. Iterators vs. Generators
    (转)iPhone开发关于UDID和UUID的一些理解
    uniqueIdentifier在ios7不支持后的替代方法
    Android——列表视图 ListView(一)Arrayadapter
    Android——对话框2(日期和时间对话框)
    Android——子线程操作主线程
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/10624072.html
Copyright © 2011-2022 走看看