CodeForces - 102D(离散+线段树/树状数组)

CodeForces - 102D

题意:0 ~ n 一共n + 1个点,我们要从0称作一些汽车到达n,每辆汽车有一个S和一个T,代表起始站和终止站,你可以在S ~ T - 1 之间任一上这辆车,但是必须在到达终点站时下车,问我们有多少种方案能到达n

思路: 由于坐标在1e9之内,所以用unique离散去重一下,我们先将每辆车的终点按从小到大排个序,那么对于每一辆车的T,它的方案就是在S ~ T - 1 之间上车的方案数,其实也就是前面的在S ~ T - 1下车方案数之和(当这辆车从0出发,再方案数++就好了),然后把这个方案数加进树状数组或者线段树里,最后到达n的那辆车的方案数就是答案,当然也可以不用这些数据结构,也有直接线性的写法,太弱了没写

代码:树状数组

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define douinf 0x3f3f3f3f
#define IO ios::sync_with_stdio(false)
#define bug cout << "-----\n"
#define eps 1e-8
typedef long long  ll;
//typedef int ll;
const int N = 100010;
const int M = 6100;
ll Mod = 1e9 + 7;
ll c[N * 2];
int li[N * 2];
int len;
struct node {
    int l,r;
    bool operator < (const node a)const {
        if(r != a.r)return r < a.r;
        return l < a.l;//可有可无
    }
}a[N];
int lowbit(int x) {
    return x & (-x);
}
void add(int i,ll x) {
    while(i <= len){
        c[i] += x;
        c[i] %= Mod;
        i += lowbit(i);
    }
}
ll find(int i) {
    ll res = 0;
    while(i > 0){
        res += c[i];
        res %= Mod;
        i -= lowbit(i);
    }
    return res;
}
int main() {
    int n,m;cin >> n >> m;
    int o = 0;
    for(int i = 0 ; i < m ; i ++) {
        cin >> a[i].l >> a[i].r;
        li[++ o] = a[i].l;
        li[++ o] = a[i].r;
    }
    sort(a , a + m);
    sort(li + 1 , li + 1 + o);
    len = unique(li + 1 , li + 1 + o) - (li + 1);
    ll res = 0;
    for(int i = 0 ; i < m ; i ++) {
        int L = lower_bound(li + 1 , li + 1 + len , a[i].l) - li;
        int R = lower_bound(li + 1 , li + 1 + len , a[i].r) - li;
        ll ans = 0;
        if(a[i].l == 0)ans = 1;
        ans += find(R - 1) - find(L - 1);
        ans %= Mod;
        add(R , ans);
        if(a[i].r == n)res = find(R) - find(R - 1);//注意这里的wa点,由于取模,前者可能小于后者,所以答案里先加个Mod
    }
    cout << (res + Mod)% Mod;
    return 0;
}

线段树:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define douinf 0x3f3f3f3f
#define IO ios::sync_with_stdio(false)
#define bug cout << "-----\n"
#define eps 1e-8
typedef long long  ll;
//typedef int ll;
const int N = 200010;
const int M = 6100;
ll Mod = 1e9 + 7;
struct Tree {
    ll l,r;
    ll num;
}tree[N * 6];
ll ans;
struct node {
    ll l,r;
    bool operator < (const node a)const {
        if(r != a.r)return r < a.r;
        return l < a.l;
    }
}a[N];
ll li[N * 2];
void build(ll x, ll l, ll r) {
    tree[x].l = l;tree[x].r = r;
    if(l == r) {
        tree[x].num = 0;
        return ;
    }
    ll mid = l + r >> 1;
    build(x << 1 , l , mid);
    build(x << 1 | 1 , mid + 1 , r);
    tree[x].num = (tree[x << 1].num + tree[x << 1 | 1].num) % Mod;
}
void update(ll x, ll pos, ll z) {
    if(tree[x].l == tree[x].r && tree[x].l == pos) {
        tree[x].num += z;
        tree[x].num %= Mod;
        return ;
    }
    if(pos <= tree[x << 1].r)update(x << 1 , pos , z);
    else if(pos >= tree[x << 1 | 1].l)update(x << 1 | 1 , pos , z);
    tree[x].num = (tree[x << 1].num + tree[x << 1 | 1].num) % Mod;
}
void find(ll x, ll l, ll r) {
    if(tree[x].l >= l && tree[x].r <= r) {
        ans += tree[x].num;
        ans %= Mod;
        return ;
    }
    if(r <= tree[x << 1].r)find(x << 1 , l , r);
    else if(l >= tree[x << 1 | 1].l)find(x << 1 | 1 , l , r);
    else {
        find(x << 1 , l , tree[x << 1].r);
        find(x << 1 | 1 , tree[x << 1 | 1].l , r);
    }
}
int main() {
    IO;
    ll o = 0;
    ll n,m;cin >> n >> m;
    for(ll i = 0 ; i < m ; i ++) {
        cin >> a[i].l >> a[i].r;
        li[++ o] = a[i].l;
        li[++ o] = a[i].r;
    }
    sort(a , a + m);
    sort(li + 1 , li + 1 + o);
    build(1 , 1 , max(o , 1ll));//由于可能没有任何车辆,所以o等于0,这里会RE
    ll res = 0;
    for(ll i = 0 ; i < m ; i ++) {
        ll L = a[i].l,R = a[i].r;
        ll l = ll(lower_bound(li + 1 , li + 1 + o , L) - li);
        ll r = ll(lower_bound(li + 1 , li + 1 + o , R) - li);
        ans = 0;
        if(a[i].l == 0)ans = 1;
        find(1 , l , r - 1);
        update(1 , r , ans);
        if(a[i].r == n) {
            ans = 0;
            find(1 , r , r);
            res = ans;
        }
    }
    cout << res % Mod << endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
引用\[1\]中提到了一种树形动态规划的方法来解决CodeForces - 982C问题。在这个问题中,subtree指的是子连通块,而不是子树。为了使cnt_white - cnt_black尽可能大,可以使用两次树形动态规划来求解。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子树中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的树链所代表的子树。在第二次遍历中,需要维护一个sum变量,用于存储树链所代表的子树的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。如果ans\[u\]为正,则减去dp\[v\]就是树链所代表的子树的权值。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] 问题: CodeForces - 982C 树形DP是什么问题?如何解决? 回答: CodeForces - 982C是一个树形动态规划问题。在这个问题中,需要求解子连通块的最大权值和,使得cnt_white - cnt_black尽可能大。解决这个问题的方法是使用两次树形动态规划。第一次是自底向上的过程,维护一个dp数组,表示以每个节点为根的子树中的最大连通块。第二次是自顶向下的过程,处理自底向上过程中无法包含的树链所代表的子树。在第二次遍历中,需要维护一个sum变量,用于存储树链所代表的子树的贡献。根据ans\[u\]的正负,决定是否能对相邻的子节点做出贡献。最终,ans\[u\]代表包含节点u在内的子连通块的最大权值。\[1\] #### 引用[.reference_title] - *1* *2* [CodeForces - 1324F Maximum White Subtree(树形dp)](https://blog.csdn.net/qq_45458915/article/details/104831678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值