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;
}