zoukankan      html  css  js  c++  java
  • 无题十二

    今天的题都有思路,但都搞不出来;

    题解:

    第一题:我看到数据范围想到了矩阵快速幂,实际上是不需要的,每次暴力乘组合数就好了,因为原来dp[i]对应前面多项,而这回dp[i]对应的dp[i-n]是唯一确定的;

    确定了前n行,后面每一行放多少就唯一确定,只需要一直乘方案数;

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int M = 105;
    const int mod=1e9 + 7;
    int c[M][M], dp[M][M*M], f[M][M];
    ll ksm(ll a, ll b){
        ll ret=1;
        for(;b;b>>=1,a=a*a%mod)
            if(b&1)ret=ret*a%mod;
        return ret;
    }
    inline int moc(int a){return a >= mod ? a - mod : a;}
    int main(){
        freopen("chess.in","r",stdin);
        freopen("chess.out","w",stdout);
        int n, C;
        ll m;
        scanf("%d%lld%d", &n, &m, &C);
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= i; j++)
                if(j == 0 || i == j) c[i][j] = 1;
                else c[i][j] = moc(c[i-1][j] + c[i-1][j-1]);
        for(int i = 1; i <= n; i++)
            for(int j = 0; j <= n; j++)
                f[i][j] = ksm(c[n][j], (m-i)/n + 1);
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++){
            for(int j=0; j <= i*n && j <= C; j++){
                int L = min(n, j);
                for(int t = 0; t <= L; t++){
                    dp[i][j] = moc(dp[i][j] + (ll)dp[i-1][j-t]*f[i][t]%mod);
                }
            }
        }
        printf("%d
    ", dp[n][C]);
    }
    View Code

    第二题:可以先用一个栈处理出每个K对应的右边第一个小于他的未知,中间的元素都>=a[k],所以只需要在中间找一个最大值且最靠左的位置,就可以最大K的最大贡献了,对应找最大值我用了一课线段数,时间空间都不行;

    考虑在弹栈的时候一并解决,pos[t]表示从栈中t这个位置到栈前下一个位置这段区间中的最大值的位置,每次弹栈时就自上往下取最大的MAX,如果栈空了,就把之前的贡献都去掉;

    我觉得我还是说不清楚,还是看代码吧,特别鸣谢:zjj

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 1e7 + 5;
    int n, a[M], q[M];
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*=f;    
    }
    int pos[M];
    int main(){
        freopen("array.in","r",stdin);
        freopen("array.out","w",stdout);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) a[i] = read();
        a[n + 1] = 0;
        int ans = 0;
        int h = 1, t = 1; q[1] = 1;
        pos[1]=1;
        int mx = 0;
        for(int i = 2; i <= n + 1; i++){
            int res= i - 1,mx = a[i - 1];
            while(h <= t && a[i] < a[q[t]]){
                ans = max(ans, res - q[t] + 1);
                if(a[pos[t]] == mx) res = max(q[t], res);
                else if(a[pos[t]] > mx) res = pos[t], mx = a[pos[t]];    
                t--;
            }    
            if(h > t)
            {
            q[++t] = i;
            pos[t] = i;
            continue;
            } 
           if(a[i] >= mx)
            {
                mx = a[i];
                res = i;
            }
            q[++t] = i;
            pos[t] = res;
        }
        printf("%d
    ", ans);
    }

    第三题:本来是莫队+线段树统计最长连续子段和,但我真的不知道那里写挂了;

    正解:回滚莫队,只带增添不带删减的莫队,每次记录版本的答案,右边一直延展,左边一直回滚

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e5 + 5;
    int n, m, a[M], ans[M];
    struct Query{int l, r, id;}q[M], qs[M];
    bool cmp1(Query A, Query B){return A.l < B.l;}
    bool cmp2(Query A, Query B){return A.r < B.r;}
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*=f;    
    }
    int L[M], R[M], vis[M], TTT, skt[M], tp, has[M], now_ans;
    void update(int t){
        if(vis[t] != TTT) vis[t] = TTT, L[t] = R[t] = t, has[t] = 0;
    }
    
    void add(int t, bool f){
        update(t), update(t+1), update(t-1);
        int lf=L[t],rg=R[t];
        if(t!=1 && has[t-1]) lf=L[t-1];
        if(t!=n && has[t+1]) rg=R[t+1];
        now_ans = max(rg - lf + 1, now_ans);
        R[lf] = rg, L[rg] = lf;
        has[t] = 1;
        if(f) skt[++tp] = t;
    }
    void restore(){
        while(tp){
            int t=skt[tp];tp--;
            has[t] = 0;
            if(t!=1 && has[t-1]) R[L[t-1]]=t-1;
            if(t!=n && has[t+1]) L[R[t+1]]=t+1;
        }
    }
    
    int main(){
        freopen("cc.in","r",stdin);
        freopen("ants.out","w",stdout);
        n = read(), m = read();
        for(int i = 1; i <= n; i++) a[i] = read();
        for(int i = 1; i <= m; i++) q[i].l = read(), q[i].r = read(), q[i].id = i;
        sort(q + 1, q + 1 + m, cmp1);
        int siz = sqrt(n + 0.5), now = 1;
        for(int i = 1, j = 1; i <= n && now <= m; i++){
            int up = min(i * siz, n), tot = 0;
            while(now <= m && q[now].l <= up)qs[++tot] = q[now++];
            if(!tot)continue; TTT++; 
            sort(qs + 1, qs + 1 + tot, cmp2);
            int now_r = up; now_ans = 1;
            for(int j = 1; j <= tot; j++){
                while(now_r < qs[j].r){
                    int t = a[++now_r];
                    add(t, 0);
                }
                int tmp = now_ans;
                for(int k = min(up, qs[j].r); k >= qs[j].l; k--) add(a[k], 1);
                ans[qs[j].id] = now_ans;
                restore();    
                now_ans = tmp;
            }
            
        }
        
        
        for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
    }
  • 相关阅读:
    Kafka 高级API 实战
    CDH 5.16.1 离线安装 Spark 2.3
    CDH5.16.1 离线安装 Kafka
    CDH5.16.1新增节点
    mysql搭建主从结构
    Kerberos常见错误
    expect实现脚本的 自动交互
    寒假day27
    寒假day26
    寒假day25
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9792368.html
Copyright © 2011-2022 走看看