The Battle of Chibi(树状数组+dp)

题目链接:The Battle of Chibi

题意:问你序列中长度为k的上升子序列有多少个。

思路(转自博客:HDU 5542 - The Battle of Chibi - [离散化+树状数组优化DP]):

  1. 首先,不难想到应当假设 dp[i][j] 代表以 a[i] 为结尾的且长度为 j 的严格单增子序列的数目,那么自然地,状态转移就是 dp[i][j]=∑dp[k][j−1],其中 k 满足 1≤k<i 且 a[k]<a[i]。
    不过,题目是不可能这么简单的……这样纯暴力dp的话时间复杂度为 O(n3),超时。

  2. 考虑进行优化:
    先对 dp 数组进行改造,假设 dp[ai][j] 代表:在数字序列的 [1,i] 区间内,以数字 a[i] 为结尾的长度为 j 的严格单增子序列的数目,这样一来,原来的 a[i] 的范围在 [1,109],数组是开不下的。所以,需要对 a[1∼n] 先进行离散化,使得所有 a[i] 的范围均在 [1,n],这样数组就开的下了。自然而然地,状态转移方程就变成了 dp[ai][j]=dp[1][j−1]+dp[2][j−1]+⋯+dp[ai−1][j−1]。

  3. 然后,既然要优化求前缀和的速度,不妨对 dp[1∼n][1] 构造一个树状数组,对 dp[1∼n][2] 构造一个树状数组,⋯,对 dp[1∼n][m] 构造一个树状数组。这样一来,我要求 dp[1][j−1]+dp[2][j−1]+⋯+dp[ai−1][j−1] 这样一个前缀和就可以在 O(logn) 时间内完成。总时间复杂度变为 O(n2logn)。那么最后所求答案即为 dp[1][m]+dp[2][m]+⋯+dp[n][m]。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#define lowbit(x) x&(-x)
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;

const ll N = 1010;
const ll mod = 1e9+7;

ll n, k;
ll a[N];
ll b[N];
ll dp[N][N];

void update(ll i, ll j, ll y)
{
    y %= mod;
    while(i <= n)
    {
        dp[i][j] += y;
        dp[i][j] %= mod;
        i += lowbit(i);
    }
}

ll query(ll i, ll j)
{
    ll ret = 0;
    while(i > 0)
    {
        ret += dp[i][j];
        ret %= mod;
        i -= lowbit(i);
    }
    return ret;
}

int main()
{
    ll t;
    scanf("%lld", &t);
    for(ll ca = 1; ca <= t; ca++)
    {
        memset(dp, 0, sizeof(dp));
        scanf("%lld %lld", &n, &k);
        for(ll i = 1; i <= n; i++)
        {
            scanf("%lld", &a[i]);
            b[i] = a[i];
        }
        sort(b+1, b+n+1);
        for(ll i = 1; i <= n; i++)
        {
            a[i] = lower_bound(b+1, b+1+n, a[i]) - b;
        }
        for(ll i = 1; i <= n; i++)
        {
            for(ll j = 1; j <= k; j++)
            {
                if(j == 1) update(a[i], 1, 1);
                else update(a[i], j, query(a[i]-1, j-1));
            }
        }
        printf("Case #%lld: %lld\n", ca, query(n, k));
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个简单的三国游戏,玩家需要在三国中完成一些任务和战斗,最终成为三国的霸主。 首先,我们需要引入一些必要的库: ```python import random import time ``` 然后,我们定义一些游戏中需要用到的变量和函数: ```python # 游戏中的角色 players = { 'player': {'name': '你', 'hp': 100, 'power': 20}, 'enemy': {'name': '敌人', 'hp': 100, 'power': 20} } # 战斗函数 def fight(player1, player2): while player1['hp'] > 0 and player2['hp'] > 0: # 玩家1攻击玩家2 player2['hp'] -= player1['power'] print(f"{player1['name']}攻击了{player2['name']},{player2['name']}剩余{player2['hp']}点生命值") # 玩家2攻击玩家1 if player2['hp'] > 0: player1['hp'] -= player2['power'] print(f"{player2['name']}攻击了{player1['name']},{player1['name']}剩余{player1['hp']}点生命值") if player1['hp'] > 0: print(f"{player1['name']}战胜了{player2['name']}") return True else: print(f"{player2['name']}战胜了{player1['name']}") return False ``` 接下来,我们定义游戏中的场景和任务: ```python # 场景1:黄巾起义 def huangjin(): print("这是黄巾起义的场景,你需要打败黄巾军") if fight(players['player'], {'name': '黄巾军', 'hp': 80, 'power': 10}): print("恭喜你,打败了黄巾军!") return True else: print("很遗憾,你输了") return False # 场景2:官渡之战 def guandu(): print("这是官渡之战的场景,你需要打败曹操的军队") if fight(players['player'], {'name': '曹军', 'hp': 100, 'power': 15}): print("恭喜你,打败了曹军!") return True else: print("很遗憾,你输了") return False # 场景3:赤壁之战 def chibi(): print("这是赤壁之战的场景,你需要打败陆逊的军队") if fight(players['player'], {'name': '陆军', 'hp': 120, 'power': 20}): print("恭喜你,打败了陆军!") return True else: print("很遗憾,你输了") return False # 任务1:拜访刘备 def liubei(): print("你需要前往刘备的营地拜访他") time.sleep(1) # 模拟时间 print("你成功拜访了刘备,他给你赠送了一把宝剑") players['player']['power'] += 10 # 任务2:寻找赵云 def zhaoyun(): print("你需要寻找赵云") time.sleep(1) # 模拟时间 print("你找到了赵云,他加入了你的队伍") players['player2'] = {'name': '赵云', 'hp': 80, 'power': 25} ``` 最后,我们将场景和任务组合在一起,实现游戏的整体流程: ```python # 游戏流程 print("欢迎来到三国世界!") time.sleep(1) # 模拟时间 # 场景1 if huangjin(): liubei() # 场景2 if guandu(): # 任务1 liubei() # 场景3 if chibi(): # 任务2 zhaoyun() print("恭喜你成为了三国的霸主!") else: print("你输了") else: print("你输了") else: print("你输了") ``` 这样,一个简单的三国游戏就完成了。当然,你可以根据自己的喜好和能力,添加更多的场景和任务,让游戏更加丰富有趣。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值