第2章の半分プレフィックスと

第2章と半分接頭辞

+++

  • 二部

  • ルーチン

更新モードは、R =半ばに書かれている場合、更新モードがL =半ばに書き込まれた場合、その後、何も処理をしない、中間の計算が必要とされ、1を加えることです。

1 789の数の範囲

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
//整数二分
using namespace std;

int st[100005];
int n, q;
int u;

int main()
{
    scanf("%d%d", &n, &q);
    for(int i = 0; i < n; i++)
        scanf("%d", &st[i]);
    while(q--)
    {
        int L = 0; int R = n - 1;
        scanf("%d", &u);
        while(L < R)
        {
            int md = L + R >> 1;
            if(st[md] >= u) R = md;//注意边界问题
            else L = md + 1;
        }
        if(st[R] == u)
        {
            cout << R << " ";
            R = n - 1;
            while(L < R)
            {
                int md = L + R + 1 >> 1;//注意边界问题
                if(st[md] <= u) L = md;
                else R = md - 1;
            }
            cout << L << endl;
        }
        else    cout << "-1 -1" << endl;
    }
    return 0;
}

2. 3 790の平方根の数

#include <iostream>
//实数二分
using namespace std;

int main()
{
    double n;
    cin >> n;
    double l = -10000, r = 10000;
    while(r - l > 1e-8)
    {
        double mid = (l + r) / 2;
        if(mid * mid * mid >= n)   r = mid;
        else l = mid;
    }
    printf("%f\n", l);
    return 0;
}

3. Aロボット跳躍の問題730

//AC code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 1e5 + 5;
int h[maxn], temp, n;

int main()
{
    cin >> n;
    for(int i = 0; i < n; i++)
        scanf("%d", h + i);
    int l = 0, r = 1e5;
    while(l < r)
    {
        int mid =(l + r) >> 1;//注意边界问题
        temp = mid;
        for(int i = 0; i < n && mid >= 0; i++)
        {
            mid = mid * 2 - h[i];
            if(mid >= 1e5)  break;   //没有这句ac不了,防止中间过程爆掉
        }
        if(mid >= 0)
            r = temp;
        else
            l = temp + 1;
    }
    cout << r << endl;
    return 0;
}

4.四平方和 1221

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 5e6;//注意
int n, m;

struct Sum{
    int s, c, d;
    
    bool operator< (const Sum &t)const
    {
        if(s != t.s)    return s < t.s;
        if(c != t.c)    return c < t.c;
        return d < t.d;
    }
}p[maxn];

int main()
{
    cin >> n;
    for(int c = 0; c * c <= n; c++ )
        for(int d = c; d * d + c * c <= n; d++ )
            p[m++] = {c * c + d * d, c, d};
    
    sort(p, p + m);
    
    for(int a = 0; a * a <= n; a++ )
        for(int b = a; b * b + a * a <= n; b++ )
        {
            int t = n - a * a - b * b;
            int l = 0, r = m - 1;
            while(l < r)
            {
                int mid = (l + r) >> 1;
                if(p[mid].s >= t)  r = mid;
                else l = mid + 1;
            }
            if(p[l].s == t)
            {
                printf("%d %d %d %d\n", a, b, p[l].c, p[l].d);
                return 0;
            }
        }
}
5.チョコレート1227ポイント
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 100010;
int n, k;
int h[maxn], w[maxn];

bool check(int u)
{
    int sum = 0;
    for(int i = 0; i < n; i++)
        sum += (h[i] / u) * (w[i] / u);
    if(sum >= k)    return true;
    return false;
}

int main()
{
    cin >> n >> k;
    for(int i = 0; i < n; i++)
        scanf("%d%d", h + i, w + i);
    int L = 1, R = 1e5;
    while(L < R)
    {
        int mid = L + R + 1 >> 1;
        if(check(mid))  L = mid;
        else R = mid - 1;
    }
    cout << R << endl;
    return 0;
}

+++

  • プレフィックスと

1.プレフィックスと795
//一维数组前缀和
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 100010;

int a[maxn], s[maxn];
int n, m;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++ )
    {
        scanf("%d", a + i);
        s[i] = s[i - 1] + a[i];//存储前i个数的和
    }
    while(m--)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        printf("%d\n", s[y] - s[x - 1]);
    }
    return 0;
}
2.サブマトリクスおよび796
// 二维数组前缀和
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 1010;
int a[maxn][maxn], s[maxn][maxn];
int n, m, q;

int main()
{
    scanf("%d%d%d", &n, &m, &q);
    for(int i = 1; i <= n; i++ )
        for(int j = 1; j <= m; j++ )
        {
            scanf("%d", &a[i][j]);
            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
        }
    while(q--)
    {
        int x1, y1, x2, y2;
        scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
        printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]);
    }
    return 0;
}
3.レーザー爆弾99
4.K時間間隔1230

//最適化時間の複雑さ

//O(n)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

const int maxn = 100010;
int s[maxn], cnt[maxn];
int n, k, temp;
LL res;

int main()
{
    cnt[0] = 1;
    cin >> n >> k;
    for(int i = 1; i <= n; i++ )
    {
        scanf("%d", &temp);
        s[i] = (s[i - 1] + temp) % k;
        res += cnt[s[i]];
        cnt[s[i]]++;
    }
    
    printf("%lld\n", res);
    return 0;
}
学んだ教訓のK倍の範囲:

1.まず、我々は試験問題は、私は暴力列挙のサイクルのための二重の複雑性O(n²)を使用し、接頭辞であるとことを知っているので、それはその後、タイムアウトしない場合、その後、ノーさらに簡素化のアイデアがあるでしょう。

2. A良いアイデアは、この質問にACコード、O(n)は、ACの成功に至るまでの複雑な単純な方法のうち暴力を最適化することです。

3.右端の後、全ての前に接頭辞を横断する権利スポットと、実際には、モッズkの後に、残りを見つけた場合、プレフィックスとのmod K K倍の範囲の性質に合わせて同じポイント。

おすすめ

転載: www.cnblogs.com/scl0725/p/12358133.html