zoukankan      html  css  js  c++  java
  • 51Nod1376 (dp + BIT // cdq分治)

    https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1376

    求LIS的数量。

    乍一看觉得还是dp,仔细一看确实可以用dp做。

    显而易见的是一个O(n2)的dp,同时维护LIS的值和cnt的数量 当然,由于数据限制,考虑优化

    我们看了题解冷静分析之后想到了用树状数组优化。

    用一个结构体node来存储len和cnt两个关键信息,重载他们之间的+运算符

    struct Node{
        LL cnt,len;
        Node(){}
        Node(int len,int cnt):len(len),cnt(cnt) {}
        Node operator + (Node t){
            if(t.len > this->len){
                return t;
            }else if(t.len < this->len){
                return (*this);
            }else{
                return Node(t.len,(t.cnt + this->cnt) % mod);
            }
        }
    }node[maxn];
    View Code

    看起来就很帅,实际上这是一个偏向比较的运算符,两个node之间长度不相等的就取长度较大的,长度相等就将两个cnt加起来。

    我们将所有的数从大到小排序,并且大小相同时编号后面的靠前,保证在遍历每个数时树状数组里所有的数都可以当作他的前缀最大值。直接上dp递推即可。

    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    const int MAXBUF=10000;char buf[MAXBUF],*ps=buf,*pe=buf+1;
    inline bool isdigit(const char& n) {return (n>='0'&&n<='9');}
    inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
    template <class T> inline bool in(T &ans){
    #ifdef VSCode
    ans=0;T f=1;register char c;
    do{c=getchar();if ('-'==c)f=-1;}while(!isdigit(c)&&c!=EOF);
    if(c==EOF)return false;do{ans=(ans<<1)+(ans<<3)+c-48;
    c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
    #endif
    #ifndef VSCode 
    ans =0;T f=1;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-1;} 
    while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<1)+(ans<<3)+*ps-48;
    rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
    #endif
    }const int MAXOUT=10000;   //*(int(*)[10])p
    char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT;
    inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
    inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
    inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
    template <class T>inline void out_int(T x) {if(!x){out_char('0');return;}
    if(x<0)x=-x,out_char('-');int len=0;while(x){outtmp[len++]=x%10+48;x/=10;}outtmp[len]=0;
    for(int i=0,j=len-1;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
    template<typename T, typename... T2>
    inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    #define Vec Point
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 5e4 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,tmp,K;
    PII a[maxn];
    struct Node{
        LL len,cnt;
        Node(){}
        Node(LL len,LL cnt):len(len),cnt(cnt){}
        Node operator + (const Node &t){
            if(this->len < t.len){
                return t;
            }
            if(this->len > t.len){
                return (*this);
            }
            return Node(t.len,(this->cnt + t.cnt) % mod);
        }
    }tree[maxn];
    int lowbit(int t){
        return t & (-t);
    }
    void update(int t,Node x){
        while(t <= N){
            tree[t] = tree[t] + x;
            t += lowbit(t);
        }
    }
    Node query(int t){
        Node s = Node(0,0);
        while(t > 0){
            s = s + tree[t];
            t -= lowbit(t);
        }
        return s;
    }
    bool cmp(PII a,PII b){
        if(a.fi != b.fi) return a.fi < b.fi;
        return a.se > b.se;
    }
    int main()
    {
        in(N);
        For(i,1,N) in(a[i].fi),a[i].se = i;
        sort(a + 1,a + 1 + N,cmp);
        Node ans(0,0);
        For(i,1,N){
            Node t = query(a[i].se - 1);
            if(++t.len == 1) t.cnt = 1;
            t.len %= mod;
            ans  = ans + t;
            update(a[i].se,t);
        }
        Prl(ans.cnt);
        #ifdef VSCode
        write();
        system("pause");
        #endif
        return 0;
    }
    View Code

    这题也可以变成一个二维偏序问题,寻找一个在len长度最大情况下的cnt,用cdq分治解决。

    #include <map>
    #include <set>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    const int MAXBUF=10000;char buf[MAXBUF],*ps=buf,*pe=buf+1;
    inline bool isdigit(const char& n) {return (n>='0'&&n<='9');}
    inline void rnext(){if(++ps==pe)pe=(ps=buf)+fread(buf,sizeof(char),sizeof(buf)/sizeof(char),stdin);}
    template <class T> inline bool in(T &ans){
    #ifdef VSCode
    ans=0;T f=1;register char c;
    do{c=getchar();if ('-'==c)f=-1;}while(!isdigit(c)&&c!=EOF);
    if(c==EOF)return false;do{ans=(ans<<1)+(ans<<3)+c-48;
    c=getchar();}while(isdigit(c)&&c!=EOF);ans*=f;return true;
    #endif
    #ifndef VSCode 
    ans =0;T f=1;if(ps==pe)return false;do{rnext();if('-'==*ps)f=-1;} 
    while(!isdigit(*ps)&&ps!=pe);if(ps==pe)return false;do{ans=(ans<<1)+(ans<<3)+*ps-48;
    rnext();}while(isdigit(*ps)&&ps!=pe);ans*=f;return true;
    #endif
    }const int MAXOUT=10000;   //*(int(*)[10])p
    char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT;
    inline void write(){fwrite(bufout,sizeof(char),pout-bufout,stdout);pout = bufout;}
    inline void out_char(char c){*(pout++)=c;if(pout==pend)write();}
    inline void out_str(char *s){while(*s){*(pout++)=*(s++);if(pout==pend)write();}}
    template <class T>inline void out_int(T x) {if(!x){out_char('0');return;}
    if(x<0)x=-x,out_char('-');int len=0;while(x){outtmp[len++]=x%10+48;x/=10;}outtmp[len]=0;
    for(int i=0,j=len-1;i<j;i++,j--) swap(outtmp[i],outtmp[j]);out_str(outtmp);}
    template<typename T, typename... T2>
    inline int in(T& value, T2&... value2) { in(value); return in(value2...); }
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    #define Vec Point
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 5e4 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,tmp,K; 
    int a[maxn];
    struct Node{
        LL cnt,len;
        Node(){}
        Node(int len,int cnt):len(len),cnt(cnt) {}
        Node operator + (Node t){
            if(t.len > this->len){
                return t;
            }else if(t.len < this->len){
                return (*this);
            }else{
                return Node(t.len,(t.cnt + this->cnt) % mod);
            }
        }
    }node[maxn];
    int id[maxn];
    bool cmp(int x,int y){
        if(a[x] == a[y]) return x > y;
        return a[x] < a[y];
    }
    void cdq(int l,int r){
        if(l == r) return;
        int m = l + r >> 1;
        cdq(l,m);
        For(i,l,r) id[i] = i;
        sort(id + l,id + r + 1,cmp);
        Node MAX = Node(0,0); 
        For(i,l,r){
            int idx = id[i];
            if(idx <= m){
                MAX = MAX + node[idx];
            }else{
                Node t = MAX;
                t.len++;
                node[idx] = node[idx] + t;
            }
        }
        cdq(m + 1,r);
    }
    int main()
    {
        in(N);
        For(i,1,N) in(a[i]);
        For(i,1,N) node[i] = Node(1,1);
        cdq(1,N);
        Node MAX = Node(0,0);
        For(i,1,N) MAX = MAX + node[i];
        Prl(MAX.cnt);
        #ifdef VSCode
        write();
        system("pause");
        #endif
        return 0;
    }
  • 相关阅读:
    spring boot 启动报错(spring-boot-devtools热部署后):The elements [spring.resources.cache-period] were left unbound. Update your application's configuration
    一分钟搞定:spring boot 热部署 (基于Idea)
    如何将新项目添加到github仓库中?只需简单几步~即可实现
    spring boot 日志文件配置(logback-spring.xml)亲测可用!
    java后台读取/解析 excel表格
    String字符串存入数据库中超出最大长度(oracle varchar2 4000)?应合理分条存储(java实现-工具/方法)
    笔试题-sql语句
    总结--看帖收“货”
    Oracle-1
    蓝桥杯- 基础练习: 字母图形
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9499738.html
Copyright © 2011-2022 走看看