题目大意:
给你许多的区间,有n个询问,每个询问给你k个点,问你包含这k个点的区间有多少个。
解决方法:
离线操作,对于每个询问的点都化成区间,比如点2,5,就可以变化成3个区间1-1,3-4,6-n,然后求包含在这些区间中的区间。
将所有区间进行排序(按照右端点的大小),然后按照顺序遍历区间,然后就可以快速的求出包含在某个区间内的区间数。
我的代码:
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <cstdio>
#define maxn 1000010
using namespace std;
struct Point {
int x,y,id;
}po[maxn];
int ans[maxn];
int tree[maxn];
int n,m;
int add(int x,int v){
for (int i=x;i<=maxn;i+=i&(-i))
tree[i]+=v;
return 0;
}
int sum(int x){
int ans=0;
for (int i=x;i>0;i-=i&(-i))
ans+=tree[i];
return ans;
}
bool cmp(Point a,Point b){
return a.x<b.x||a.x==b.x&&a.y>b.y||a.x==b.x&&a.y==b.y&&a.id>b.id;
}
int main (){
//freopen("test.in","r",stdin);
while (~scanf("%d%d",&n,&m)){
memset(tree,0,sizeof(tree));
for (int i=1;i<=n;i++)
scanf("%d%d",&po[i].x,&po[i].y),po[i].id=0;
for (int i=1;i<=m;i++) ans[i]=n;
int totl=n;
for (int i=1;i<=m;i++){
int op,x;scanf("%d%d",&op,&x);
if (x>1) {
po[++totl].x=1;
po[totl].y=x-1;
po[totl].id=i;
}
//cout<<op<<endl;
op--;
while (op--){
int nows;scanf("%d",&nows);
po[++totl].x=x+1;
po[totl].y=nows-1;
po[totl].id=i;
x=nows;
}
if (x+1<maxn) {
po[++totl].x=x+1;
po[totl].y=maxn-1;
po[totl].id=i;
}
}
sort(po+1,po+totl+1,cmp);
for (int i=totl;i>=1;i--){
if (po[i].id) ans[po[i].id]-=sum(po[i].y);
else add(po[i].y,1);
}
for (int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
return 0;
}