zoukankan      html  css  js  c++  java
  • bzoj4904 [Ctsc2017]最长上升子序列

    我们发现他让求的东西很奇怪,于是通过某D开头定理,我们转化为前m位的序列用k个不上升子序列最多能覆盖多少。数据范围小的时候可以网络流做,但是这道题显然不支持网络流的复杂度。然后有一个奇怪的东西叫杨氏矩阵,详见acdreamers    acdreamers。但是我们又不能每次O(k)来扫,之后又有一个神奇的性质就是对于反串建的这个矩阵的形状和原矩阵转置的形状是一样的,于是我们可以在原矩阵中找到前$sqrt{n}$个,之后的长度肯定小于$sqrt{n}$于是我们就可以在转置后的矩阵中计算了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define N 50505
     7 #define M 233
     8 using namespace std;
     9 struct data{int pos,K,id,ans;}d[N<<2];
    10 bool cmp1(data a,data b){return a.pos<b.pos;}
    11 bool cmp2(data a,data b){return a.id<b.id;}
    12 int n,m,a[N];
    13 namespace A{
    14     int a[M+10][N],len[M+10];
    15     void insert(int x,int y,int v){
    16         if(x>M)return ;
    17         y=min(y,len[x]);
    18         while(y&&a[x][y]<v)y--;y++;
    19         if(y>len[x]){
    20             a[x][++len[x]]=v;
    21             return;
    22         }
    23         else{
    24             insert(x+1,y,a[x][y]);
    25             a[x][y]=v;
    26         }
    27     }
    28 };
    29 namespace B{
    30     int a[M+10][N],len[M+10];
    31     void insert(int x,int y,int v){
    32         if(x>M)return ;
    33         y=min(y,len[x]);
    34         while(y&&a[x][y]>=v)y--;y++;
    35         if(y>len[x]){
    36             a[x][++len[x]]=v;
    37             return;
    38         }
    39         else{
    40             insert(x+1,y,a[x][y]);
    41             a[x][y]=v;
    42         }
    43     }
    44 };
    45 int query(int x){
    46     int ans=0;
    47     for(int i=1;i<=x&&i<=M;i++)
    48         ans+=A::len[i];
    49     if(x>M){
    50         for(int i=1;i<=M&&B::len[i]>M;i++)
    51             ans+=min(B::len[i],x)-M;
    52     }
    53     return ans;
    54 }
    55 int main(){
    56     scanf("%d%d",&n,&m);
    57     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    58     for(int i=1;i<=m;i++)
    59         scanf("%d%d",&d[i].pos,&d[i].K),d[i].id=i;
    60     sort(d+1,d+m+1,cmp1);
    61     for(int i=1,j=1;i<=n;i++){
    62         A::insert(1,N,a[i]);
    63         B::insert(1,N,a[i]);
    64         for(;j<=m&&d[j].pos==i;j++)
    65             d[j].ans=query(d[j].K);
    66     }
    67     sort(d+1,d+m+1,cmp2);
    68     for(int i=1;i<=m;i++)
    69         printf("%d
    ",d[i].ans);
    70     return 0;
    71 }
    View Code
  • 相关阅读:
    验证字符串空“” 的表达式
    should not this be a private conversation
    【转】你真的了解word-wrap 和 word-break 的区别吗
    To live is to function,that is all there is in living
    [转] windows 上用程序putty使用 ssh自动登录Linux(Ubuntu)
    Vim/gvim容易忘记的快捷键
    [转] Gvim for windows中块选择的方法
    问题集
    web services
    Trouble Shooting
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8804453.html
Copyright © 2011-2022 走看看