zoukankan      html  css  js  c++  java
  • 湘潭邀请赛 2017 题解

    E :Partial Sum

      每次取任意两个不同的前缀,取过之后不能再取,最多取M次

      将前缀和排序,优先取最大,最小就行了

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 5e5+10, M = 1e3+20, mod = 1e9+7,inf = 2e9;
    
    int n,m,c,sum[N],a[N],b[N];
    int main() {
        while(scanf("%d%d%d",&n,&m,&c)!=EOF) {
            sum[0] = 0;
            int cnt =0;
            b[++cnt] = 0;
            for(int i = 1; i <= n; ++i) {
              scanf("%d",&a[i]);
              sum[i] = sum[i-1] + a[i];
              b[++cnt] = sum[i];
            }
            sort(b+1,b+cnt+1);
            int head = 1, tail = cnt;
            LL ans = 0;
            for(int i = 1; i <= m; ++i) {
                int f = b[head++];
                int s = b[tail--];
                if(abs(s-f)-c >= 0) {
                    ans += abs(s-f)-c;
                }
                else break;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    E

    F:Longest Common Subsequence

      将a数组离散化,枚举三元素,n^3

      求LCS,花费n*3,现在总体复杂度是n^4的

      求LCS这步可以 优化,我们预处理吃nex[i][c],当前i位置后面第一个c在哪里

      就可以在2^3下O(1)求出LCS了

      有个坑的地方就是 a[i]可能会大于m,wa了很久

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 2e2+10, M = 1e3+20, mod = 1e9+7,inf = 2e9;
    
    
    LL n,m,a[N],c,b[N],nex[N][N];
    LL v[N];
    LL f[N];
    LL query(LL x) {
        return lower_bound(b+1,b+c+1,x) - b;
    }
    int main() {
        while(scanf("%lld%lld",&n,&m)!=EOF) {
            for(int i = 1; i <= n; ++i)
                scanf("%lld",&a[i]),b[i] = a[i];
            sort(b+1,b+n+1);
            c = unique(b+1,b+n+1) - b - 1;
            for(int i = c; i >= 1; --i) {
                if(b[i] > m) c--;
                else break;
            }
            for(int i = 0; i <= 5; ++i) f[i] = 0;
            for(int i = 1; i <= n; ++i) a[i] = query(a[i]);
            memset(nex,0,sizeof(nex));
            memset(v,0,sizeof(v));
            
            for(int i = 0; i <= n; ++i) {
                for(int j = 1; j <= c; ++j) {
                    for(int k = i+1; k <= n; ++k) {
                        if(a[k] == j) {
                            nex[i][j] = k;
                            break;
                        }
                    }
                }
            }
            
            for(int i = 1; i <= c; ++i) v[i] = 1;
            
            v[c+1] = m - c;
            
            for(int i = 1; i <= c+1; ++i) {
                for(int j = 1; j <= c+1; ++j) {
                    for(int k = 1; k <= c+1; ++k) {
    
                        int fi = 0, se = 0, th = 0;
    
                        for(int C = 1; C < 8; ++C) {
                            int now = 0;
                            if(C&(4)) {
                                if(!nex[now][i]) {continue;}
                                else now = nex[now][i];
                            }
                            if(C&(2)) {
                                if(!nex[now][j]) {continue;}
                                else now = nex[now][j];
                            }
                            if(C&(1)) {
                                if(!nex[now][k]) {continue;}
                                else now = nex[now][k];
                            }
    
                            if(C == 7) fi = 1;
                            else if(C == 6 || C == 5 || C == 3) se = 1;
                            else if(C)th = 1;
                            
                        }
    
                        if(fi){
                            f[3] += v[i]*v[j]*v[k];
                        }
                        else if(se) {
                            f[2] += v[i]*v[j]*v[k];
                        }
                        else if(th) {
                            f[1] += v[i]*v[j]*v[k];
                        }
                        else {
                            f[0] += v[i]*v[j]*v[k];
                        }
                        
                        
                    }
                }
            }
    
            for(int i = 0; i < 3; ++i) cout<<f[i]<<" ";
            cout<<f[3]<<endl;
    
        }
        return 0;
    }
    F

     H:Highway

      求一次树的直径

      再从直径的两个端点做一次bfs最短路

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e5+10, M = 1e3+20, mod = 1e9+7,inf = 2e9;
    
    
    struct ss{
        int to,next,c;
    }e[N * 2];
    int head[N],t = 1;
    LL sum,mx[N],dp[N];
    int from,q[N],vis[N],n;
    void add(int u,int v,int w) {
        e[t].to = v;
        e[t].next = head[u];
        e[t].c = w;
        head[u] = t++;
    }
    void dfs(int u,int f,LL dep) {
        if(dep > sum) {
            sum = dep;
            from = u;
        }
        for(int i = head[u]; i; i = e[i].next) {
            int to = e[i].to;
            if(to == f) continue;
            dfs(to,u,dep + e[i].c);
        }
    }
    void bfs(int u) {
        int l = 0,r = 1;
        q[++l] = u;
        dp[u] = 0;
        while(l <= r) {
            int k = q[l++];
            for(int i = head[k]; i; i = e[i].next) {
                int to = e[i].to;
                if(vis[to]) continue;
                dp[to] = dp[k] + e[i].c;
                vis[to] = 1;
                q[++r] = to;
            }
        }
        for(int i = 0; i <= n; ++i) vis[i] = 0,mx[i] = max(mx[i],dp[i]);
    }
    void init() {
        t =1;
        memset(head,0,sizeof(head));
        for(int i  =0; i <= n; ++i) vis[i] = 0,mx[i] = 0;
    }
    int main() {
        while(scanf("%d",&n)!=EOF) {
            init();
            for(int i = 1; i < n; ++i) {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
            }
            sum = 0;
            dfs(1,0,0);
            int fi = from;
            sum = 0;
            dfs(from,0,0);
            LL ans = sum;
            bfs(fi);
            bfs(from);
            for(int i = 1; i <= n; ++i) {
                if(i != fi && i != from) ans += mx[i];
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    H

     J:Similar Subsequence

      设 f(i, j, x, y) 表示分别匹配到 ai 和 bj,数字的上界和下界分别是 x 和 y 的方案数。

         注意到 x 和 y 总有一个等于 bj,所以状态数是 nm2 的。

         转移就是枚举 ai+1 匹配的是 bk,要求 bk 落在 [x, y] 中。

         这个可 以用树状数组优化。复杂度是 O(nm2 log m).题解来自icpccamp;

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #include<algorithm>
    using namespace std;
    
    typedef long long ll;
    typedef double db;
    
    const int mod=1000000007;
    
    int t,n,m;
    int A[25],B[510];
    int dp[25][510][510];
    int a[25][510][510];
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void add(int id,int bd,int x,int v)
    {
        while(x)
        {
            a[id][bd][x]+=v;
            if(a[id][bd][x]>=mod) a[id][bd][x]-=mod;
            if(a[id][bd][x]<0) a[id][bd][x]+=mod;
            x-=lowbit(x);
        }
    }
    
    int sum(int id,int bd,int x)
    {
        int res=0;
        while(x<=m)
        {
            res+=a[id][bd][x];
            if(res>=mod) res-=mod;
            x+=lowbit(x);
        }
        return res;
    }
    
    int main()
    {
    #ifdef Haha
        //freopen("in.in","r",stdin);
    #endif // Haha
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(int i=1; i<=n; i++) scanf("%d",&A[i]);
            for(int i=1; i<=m; i++) scanf("%d",&B[i]);
            memset(dp,0,sizeof(dp));
            memset(a,0,sizeof(a));
            if(A[1]==0) add(1,m,m,1);
            else add(1,1,m,1);
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    for(int k=1; k<=m; k++)
                    {
                        dp[i][j][k]=sum(i,k,B[j]);
                        //printf("%d %d %d %d
    ",i,j,k,dp[i][j][k]);
                    }
                    if(i==1) continue;
                    for(int k=1; k<=m; k++)
                    {
                        if(dp[i-1][j][k]==0) continue;
                        int L,R;
                        if(A[i-1]==0) L=B[j],R=k;
                        else L=k,R=B[j];
                        if(L>R) continue;
                        
                        if(A[i]==0)
                        {
                            add(i,R,R,dp[i-1][j][k]);
                            add(i,R,L-1,-dp[i-1][j][k]);
                        }
                        else
                        {
                            add(i,L,R,dp[i-1][j][k]);
                            add(i,L,L-1,-dp[i-1][j][k]);
                        }
                    }
                }
            }
            int ans=0;
            for(int i=1; i<=m; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    ans+=dp[n][i][j];
                    if(ans>=mod) ans-=mod;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    J
  • 相关阅读:
    LeetCode15.3 Sum
    LeetCode215. Kth Largest Element in an Array
    python基础结构的时间复杂度
    顺时针打印矩阵
    合并k个有序链表
    LeetCode3. Longest Substring Without Repeating Characters
    决策树剪枝问题
    LeetCode98. Validate Binary Search Tree
    LeetCode96. Unique Binary Search Trees
    Visio软件不能使用方向键移动图形的解决办法
  • 原文地址:https://www.cnblogs.com/zxhl/p/6858560.html
Copyright © 2011-2022 走看看