群赛 ZOJ3741(dp) ZOJ3911(线段树)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了群赛 ZOJ3741(dp) ZOJ3911(线段树)相关的知识,希望对你有一定的参考价值。

zoj3741

简单dp。wa了两个小时,中间改了好多细节。后来还是不对,参考了别人的代码,发现一个致命问题,初始化的时候,不是每种状态都能直接达到的。初始化成-1。

(题目有个小坑,0<=L<=5, 即使吃药了,也不能到6 )

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#define pk printf("lalala");
using namespace std;
#define PI acos(-1.0)
#define EXP exp(1.0)	// 自然对数
#define ESP 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
typedef long long ll;
const int N = 105;
int dp[N][2*N];
int a[N];

void print()
{
    for (int k = 1; k <= 6; ++k) {
        for (int i = 98; i <= 101; ++i)
            printf("%d ", dp[k][i]);
        printf("\n");
    }

}

int main()
{
    int l, n, x, y;
    while (~scanf("%d%d%d%d", &l, &n, &x, &y)) {
        clr(dp, -1);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        dp[0][100] = 0;
        for (int i = 1; i <= n; ++i) {
            for (int j = 100 - y; j <= 100 + x; ++j) {
                if (j == 100 - y) {
                    if (dp[i - 1][100 + x] == -1) continue;
                    if (0 >= a[i]) dp[i][j] = dp[i - 1][100 + x] + 1;
                    else dp[i][j] = dp[i - 1][100 + x];
                } else if (j < 100) {
                    if (dp[i - 1][j - 1] == -1) continue;
                    if (0 >= a[i]) dp[i][j] = dp[i - 1][j - 1] + 1;
                    else dp[i][j] = dp[i - 1][j - 1];
                } else if (j == 100 + 1) {
                    if (dp[i - 1][j - 1] == -1 && dp[i - 1][100 - 1] == -1) continue;
                    if ((l + 1 <= 5 && l + 1 >= a[i]) || l >= a[i]) {
                        dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][100 - 1]) + 1;
                    } else {
                        dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][100 - 1]);
                    }
                } else if (j > 100) {
                    if (dp[i - 1][j - 1] == -1) continue;
                    if ((l + 1 <= 5 && l + 1 >= a[i]) || l >= a[i]) dp[i][j] = dp[i - 1][j - 1] + 1;
                    else dp[i][j] = dp[i - 1][j - 1];
                } else {
                    if (dp[i - 1][j] == -1 && dp[i - 1][100 - 1] == -1) continue;
                    if (l >= a[i]) {
                        dp[i][j] = max(dp[i - 1][j], dp[i - 1][100 - 1]) + 1;
                    } else {
                        dp[i][j] = max(dp[i - 1][j], dp[i - 1][100 - 1]);
                    }
                }
            }
        }
        int ans = 0;
        for (int i = 100 - y; i <= 100 + x; ++i) {
            ans = max(ans, dp[n][i]);
        }
        //print();
        printf("%d\n", ans);
    }
    return 0;
}

/*
3 6 1 2
1 3 4 5 6 4

0 6 3 1
1 0 1 0 1 0

3 6 1 3
3 4 3 3 4 4

3 6 1 2
3 4 3 4 3 4

3 6 1 2
4 5 4 5 4 5

5 6 1 2
6 5 6 4 5 6

5 6 2 3
6 5 6 5 6 5

4 6 1 6
5 5 5 5 5 5

4 6 5 2
5 5 0 0 5 5


4
6
4
4
2
3
3
1
5
*/

  

zoj 3911

线段树区间更新,点更新,区间查询。好久不写,不是很会写了 (尴尬 - -#)

#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <utility>		// pair
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#define pk printf("lalala");
using namespace std;
#define PI acos(-1.0)
#define EXP exp(1.0)	// 自然对数
#define ESP 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
typedef long long ll;

const int MAX_N = 10000005;
int prime[MAX_N];
bool is_prime[MAX_N];

int sieve(int n)
{
	int p = 0;
	for (int i = 0; i <= n; ++i) is_prime[i] = true;
	is_prime[0] = is_prime[1] = false;
	for (int i = 2; i <= n; ++i) {
		if (is_prime[i]) {
			prime[p++] = i;
			for (int j = 2 * i; j <= n; j += i)
				is_prime[j] = false;
		}
	}
	return p;
}

#define lson (o<<1)
#define rson (o<<1|1)
#define mid ((l+r)>>1)

const int N = 100005;
int tr[N * 3];
int ans[N * 3];
int v, yl, yr;

void pushup(int o)
{
    ans[o] = ans[lson] + ans[rson];
}

void build(int o, int l, int r)
{
    if (l == r) {
        scanf("%d", &tr[o]);
        if (is_prime[ tr[o] ]) ans[o] = 1;
        else ans[o] = 0;
        return ;
    }
    build(lson, l, mid);
    build(rson, mid + 1, r);
    pushup(o);
}

void pushdown(int o, int l, int r)
{
    if (tr[o] == 0) return ;
    tr[lson] = tr[rson] = tr[o];
    if (is_prime[ tr[o] ]) {
        ans[lson] = mid - l + 1;
        ans[rson] = r - mid;
    } else {
        ans[lson] = ans[rson] = 0;
    }
    tr[o] = 0;
}

void add(int o, int l, int r)
{
    if (l == r) {
        tr[o] += v;
        if (is_prime[ tr[o] ]) ans[o] = 1;
        else ans[o] = 0;
        return ;
    }
    pushdown(o, l, r);
    if (mid >= yl) add(lson, l, mid);
    else add(rson, mid + 1, r);
    pushup(o);
}

void update(int o, int l, int r)
{
    if (yl <= l && yr >= r) {
        tr[o] = v;
        if (is_prime[v]) {
            ans[o] = r - l + 1;
        } else {
            ans[o] = 0;
        }
        return ;
    }
    pushdown(o, l, r);
    if (yl <= mid) update(lson, l, mid);
    if (yr > mid) update(rson, mid + 1, r);
    pushup(o);
}

int query(int o, int l, int r)
{
    if (yl <= l && yr >= r) return ans[o];
    pushdown(o, l, r);
    int res = 0;
    if (yl <= mid) res += query(lson, l, mid);
    if (yr > mid) res += query(rson, mid + 1, r);
    return res;
}

int main()
{
    sieve(10000000);

    int t;
    scanf("%d", &t);
    while (t--) {
        int n, q;
        scanf("%d%d", &n, &q);
        clr(tr, 0);
        build(1, 1, n);

        while (q--) {
            char op[4];
            scanf("%s", op);
            if (*op == ‘A‘) {
                scanf("%d%d", &v, &yl);
                add(1, 1, n);
            } else if (*op == ‘R‘) {
                scanf("%d%d%d", &v, &yl, &yr);
                update(1, 1, n);
            } else {
                scanf("%d%d", &yl, &yr);
                printf("%d\n", query(1, 1, n));
            }
        }
    }

    return 0;
}

  

以上是关于群赛 ZOJ3741(dp) ZOJ3911(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

ZOJ1610 线段树

ZOJ 3772 线段树

ZOJ-1610 Count the Colors ( 线段树 )

ZOJ 1610 Count the Color(线段树)

ZOJ 2859 二维线段树

ZOJ - 1610 Count the Colors 线段树区间修改