题意:
有中文题面
分析:
我们发现b1,b2,...,bx都加1就相当于bx+1,bx+2,...,bn都减1
我们只要用两个set来维护两组人,同时维护一个减去的delta,每次被消灭的从对应的set中删去就好了
由于元素最多被删去n次,复杂度为O(nlogn)
坑:
−−元素可能重复,应该用multiset!
代码:
//
// Created by TaoSama on 2015-12-12
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e4 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m;
int a[N], b[N], c[N];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
memset(c, 0, sizeof c);
for(int i = 1; i <= m; ++i) {
int x; scanf("%d", &x);
++c[x];
}
multiset<int> x, y;
multiset<int>::iterator iter;
int delta = 0;
for(int i = 1; i <= n; ++i) {
b[i] -= delta;
if(a[i]) {
iter = y.upper_bound(b[i]);
y.erase(y.begin(), iter);
x.insert(b[i]);
} else {
iter = x.upper_bound(b[i]);
x.erase(x.begin(), iter);
y.insert(b[i]);
}
delta += c[i];
}
printf("%d\n", x.size() + y.size());
}
return 0;
}
分析:
与上面的思想类似,我们可以不用set,我们考虑倒过来做,这个时候要预处理ci前缀和
我们只要维护从后往前两组对应的最大值,就知道当前这个人会不会被消灭了,因为他被消灭只和他后面的人有关系
这样就优化到了O(n)
代码:
//
// Created by TaoSama on 2015-12-12
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, m;
int a[N], b[N], c[N];
int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
// freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d%d", a + i, b + i);
memset(c, 0, sizeof c);
for(int i = 1; i <= m; ++i) {
int x; scanf("%d", &x);
++c[x];
}
for(int i = 1; i <= n; ++i)
c[i] += c[i - 1];
int maxv[] = { -INF, -INF}, ans = n;
for(int i = n; i; --i) {
int t = a[i];
b[i] -= c[i - 1];
if(b[i] < maxv[t ^ 1]) --ans;
maxv[t] = max(maxv[t], b[i]);
}
printf("%d\n", ans);
}
return 0;
}