开学第九测

      开学第九测

  一不小心从第六蹦到了第九,第七还没写,第八还没写完 还是太懒了啊  2333

  这套题是 dalao RMY 自己出从网上扒而且他自己还不会


  T1  模拟只会猜题意

 思路:数据输入同时处理处前缀和,然后枚举区间长度,处理处 1 ~ n 的答案,随后查询即可

 时间复杂度:O( n2 + m )

#include<iostream>
#include<cstdio>
#define M 100005
using namespace std;
int n, m;
int a[M], sum[M], ans[M];
int read() {
    int x = 0, c, f = 1;
    while(!isdigit(c = getchar())) if(c == '-') f = -1;
    while(x = x * 10 + c - '0', isdigit(c = getchar()));
    return x * f;
}
int main(){
//    freopen("test.in","r",stdin);
//    freopen("test.out","w",stdout);
    n = read(), m = read();
    for(int i = 1; i <= n; i++) a[i] = read(), sum[i] = sum[i - 1] + a[i];
    for(int i = 1; i <= n; i++) {
        ans[i] = -1e9;
        for(int j = 1; i + j <= n + 1; j++)
            ans[i] = max(ans[i], sum[j + i - 1] - sum[j - 1]);
    }
    for(int i = n - 1; i >= 1; i--)
        ans[i] = max(ans[i], ans[i+1]);
    while(m--)
        printf("%d\n", ans[read()]);
    return 0;
}
View Code

  T2  DP一般看规律

  思路:分四种情况讨论

    dp[i][j] 为找到 i 种 bug j 个子系统 到达目标的期望

    dp[i][j] 找到一个新 bug 属于已找到的种类并且属于已找到的子系统概率 p1 = i/n * j/s;

    dp[i+1][j] 找到一个新 bug 不属于已找到的种类属于已找到的子系统概率 p2 = (n-i)/n * j/s;

    dp[i][j+1] 找到一个新bug不属于已找到的系统属于已找到的种类 概率 p3 = i/n * (n-j)/s;

    dp[i+1][j+1] 找到一个新 bug 既不属于已找到的系统也不属于已找到的种类 概率 p4 = (n-i)/n * (s-j)/s;

    所以dp方程为 dp[i][j] = p1*dp[i][j] + p2*dp[i+1][j] + p3*dp[i][j+1] + p4*dp[i+1][j+1] + 1;

#include<cstdlib>
#include<cstring>
#include<cstdio>
#define M 1005
using namespace std;
int n, s;
double p1, p2, p3, p4;
double dp[M][M];

int main() {
//    freopen("bug.in","r",stdin);
//    freopen("bug.out","w",stdout);
    while(scanf("%d%d", &n, &s) != EOF) {
        memset(dp, 0, sizeof dp);
        for(int i = n; i >= 0; i--) {
            for(int j = s; j >= 0; j--) {
                if(i == n && j == s) continue;
                p1 = 1.0 * i/n * j/s;
                p2 = 1.0 * (n-i)/n * j/s;
                p3 = 1.0 * i/n * (s-j)/s;
                p4 = 1.0 * (n-i)/n * (s-j)/s;
                dp[i][j] = (p2*dp[i+1][j] + p3*dp[i][j+1] + p4*dp[i+1][j+1] + 1.0) / (1.0 - p1);
            }
        }
        printf("%.4f\n", dp[0][0]);
    }
//    fclose(stdin);fclose(stdout);
    return 0;
}
View Code

  T3  数学上来先打表

 思路:我们先想暴力怎么做: 把一段区间的数取出来, 排个序, 从小到大选择。如果 a1~ai−1 能够表示 1 x,此时加入 ai,如果 ai≤x+1,那么就可以表示 x+ai,否则 x 就是答案。

    试着优化一下这个过程: 设ai−1=k, ai=y, 1~i-1的神秘数为ans=x+1,那么显然ans=∑t=1i−1。 此时如果存在k+1~ans的数就可以更新ans。更具体地,如果 k+1~ans 内的数的和为 s,那么 ans+=s;而 ans 为1~k 的数的和+1,故 ans 的新值应该赋为 1~ans 的数的和。

    说了这么多废话有什么用?我们可以发现每次 ans 的增量都大于等于前一次的 ans,所以这个过程的时间复杂度应该为 O(loga)。

    而事实上我们并不能把区间拿出来排序,所以需要使用数据结构,上一个主席树就好了。  然而并不会写 2333

 时间复杂度为 O(nlog2n)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cstdio>
#include<cmath>
#define M 200005
#define MM 5000005
using namespace std;
int n, m, mm, ind;
int s[MM], a[M];
int root[MM], ch[MM][2];

inline void update(int &root, int oldrt, int l, int r, int x) {
    root = ++ind;
    if(l == r) {
        s[root] = s[oldrt] + x;
        return ;
    }
    int mid = l+r >> 1;  //这里是先算 l+r ,后算 >> 1 
    if(x <= mid) ch[root][1] = ch[oldrt][1], update(ch[root][0], ch[oldrt][0], l, mid, x);
    if(x > mid) ch[root][0] = ch[oldrt][0], update(ch[root][1], ch[oldrt][1], mid+1, r, x);    
    s[root] = s[ch[root][0]] + s[ch[root][1]];    
}

inline int query(int rootx, int rooty, int l, int r, int ql, int qr) {
    if(ql <= l && r <= qr) return s[rootx] - s[rooty];
    int mid = l+r >> 1;
    if(qr <= mid) return query(ch[rootx][0], ch[rooty][0], l, mid, ql, qr);
    else if(ql > mid) return query(ch[rootx][1], ch[rooty][1], mid+1, r, ql, qr);
    else return query(ch[rootx][0], ch[rooty][0], l, mid, ql, qr) + query(ch[rootx][1], ch[rooty][1], mid+1, r, ql, qr);
}

inline int qu(int l, int r) {
    int lasgg = 1111111111;
    for (int t = 1, gg; ; ) {
        gg = query(root[r], root[l-1], 1, mm, 1, t);
        if(gg == lasgg) return t;
        t = gg + 1;
        lasgg = gg;
    }
}

int main() {
//    freopen("mystic.in","r",stdin);
//    freopen("mystic.out","w",stdout);
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if(a[i] > mm) mm = a[i];
    }
    for(int i = 1; i <= n; i++)
        update(root[i], root[i - 1], 1, mm, a[i]);
    scanf("%d", &m);
    for(int i = 1, l, r; i <= m; i++) {
        scanf("%d%d", &l, &r);
        printf("%d\n", qu(l, r));
    }
//    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/v-vip/p/9302158.html
今日推荐