题意:给定n(n<=100000)个区间(左闭右开)和m(m<=100000)次询问[l, r],问所有在[l, r]区间内最多有多少个两两不相交的区间。,
思路:首先贪心的思想,去除掉包含其他区间的大区间,这样做肯定不会影响结果。
然后对于所有区间,按照左端点升序排序,那么由于这时所有区间不相互包含,他们的右端点也是递增的。
那么对于每个询问,肯定是从左到右去尽可能多的区间,这个贪心容易想到。
对数据离散化,记录从每个点开始的经过i个区间所达到的最近距离,这一步用到了倍增的思想,因为如果一个点一个点顺序找,那么时间复杂度和空间复杂度都无法承受。
具体来说,用f[i][j]记录从i出发经过2^j个区间所达到的最近点,那么可以得出递推关系
f[i][j] = f[ f[i][j-1] ][j-1];
那么对于每个询问,我们将询问ql,qr也离散化,只需找到从ql最多经过多少区间使得其不超过qr即可。
ps:半夜睡不着真是心痛,起来补题.........
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #define eps 1e-6 #define LL long long #define pii (pair<int, int>) //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int maxn = 100000 + 100; const int INF = 0x3f3f3f3f; int n, m; struct Node { int l, r; bool operator < (const Node& A) const { if(l == A.l) return r > A.r; return l < A.l; } } node[maxn]; int discret[2*maxn]; int fa[2*maxn][20]; int solve(int l, int r) { int ans = 0; for(int i = 16; i >= 0; i--) { int t = fa[l][i]; // cout << t << endl; if(t == r) return ans+(1<<i); else if(t < r) l = t, ans += (1<<i); } return ans; } int main() { // freopen("input.txt", "r", stdin); while(scanf("%d%d", &n, &m) == 2) { memset(fa, INF, sizeof(fa)); for(int i = 0; i < n; i++) { scanf("%d%d", &discret[2*i], &discret[2*i+1]); node[i].l = discret[2*i], node[i].r = discret[2*i+1]; } sort(discret, discret+2*n); int cnt = unique(discret, discret+2*n)-discret; //cout << cnt << endl; for(int i = 0; i < n; i++) { node[i].l = lower_bound(discret, discret+cnt, node[i].l) - discret; node[i].r = lower_bound(discret, discret+cnt, node[i].r) - discret; // cout << node[i].r << endl; } sort(node, node+n); int cnt2 = n-1; for(int i = cnt-1; i >= 0; i--) { // cout << node[i].l << endl; if(i == node[cnt2].l) { fa[i][0] = min(node[cnt2].r, fa[i+1][0]); while(i == node[cnt2].l) cnt2--; } else fa[i][0] = fa[node[cnt2+1].l][0]; } for(int i = 1; i < 17; i++) { for(int j = 0; j < cnt; j++) if(fa[j][i-1] != INF) fa[j][i] = fa[ fa[j][i-1] ][i-1]; } for(int i = 0; i < m; i++) { int l, r; scanf("%d%d", &l, &r); l = lower_bound(discret, discret+cnt, l) - discret; r = upper_bound(discret, discret+cnt, r) - discret - 1; // cout << l << " " << r << endl; printf("%d\n", solve(l, r)); } //cout << fa[0][0] << endl; } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-08 09:50:55