Description
前两天,爱的战士ZZQ向我讨教了一个问题,这个问题可以用线性规划来描述。貌似用线性规划描述出来后,配合以单纯形法就可以求解了?对于这种问题,我果断表示不会。后来ZZQ 告诉我,原来这个问题是可以转化为一个等价问题的:一开始有N(1≤N≤3∗10^5 )条线段,第i条线段覆盖的区间为[Li,Ri](其中1<=Li<=Ri<=10^6),然后有M(1≤M≤3∗10^5)个组,第i个组包含了Ki(1≤Ki<=3*10^5)个点,这Ki个点所在的位置分别用P1,P2,…,PKi
来表示,为了方便观察,我们令1<=P1 < P2 < … < PKi <=10^6
我们还可以知道,这M个组的点的数目加起来不超过3*10^5现在的问题是,对于每一个组给出来的一系列的点,我们要求出一共有多少条线段,包含了给定的点中的至少一个点。我对于这个转化的等价问题还是毫无头绪,于是决定私下找你来帮忙,为了不被爱的战士ZZQ 狂虐,你一定要帮帮我啊!
Input
多组数据(不超过30组)
对于每组数据,第一行两个整数N和M,分别代表线段的数量和M个分组。接下来的N行,每行包含了2个整数Li和Ri,表示第i条线段的起始和结束位置。接下来的M行,每行第一个整数是K,表示该分组一共有K个点,接下来给出了K个点的坐标位置P1 ,P2 ,……,Pk(1<=P1 < P2 < … < PK<=10^6)
Output
对于每个分组,输出一个整数Ans,表示一共有Ans条线段,这Ans条线段分别包含了组里的至少一个点
Sample Input
3 3
1 3
4 5
6 7
3 1 4 7
2 4 5
1 8
Sample Output
3
1
0
Solution
对于某组点,考虑不包含这些点的线段,那么这些线段只会出现在两个点中间或者是所有点的两边,用一个线段表示相邻的两点,那么P1~Pk这k个点就变成了-1~P1,P1~p2,…,Pk-1~Pk,Pk~INF这k+1条线段(后称为新线段),将m次查询所得到的所有的这些线段按右端点排序,再将所有原先的线段(后称为老线段)按右端点排序,枚举新线段,对于某个线段[l,r],将所有右端点严格小于r的老线段的左端点插到树状数组中,然后查询树状数组中所有小于等于r-1的数的个数以及所有小于等于l的数的个数,两者相减即为所有左端点严格大于l,右端点严格小于r的老线段的个数,将这个个数累加到这个新线段对应的组的答案中即可
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1111111
int n,m,ans[maxn];
struct node
{
int l,r,id;
node(){};
node(int _l,int _r,int _id)
{
l=_l,r=_r,id=_id;
}
bool operator <(const node &a)const
{
return r<a.r;
}
}p[maxn],q[maxn];
struct BIT
{
#define lowbit(x) (x&(-x))
int b[maxn];
void init()
{
memset(b,0,sizeof(b));
}
void update(int x,int v)
{
while(x<maxn)
{
b[x]+=v;
x+=lowbit(x);
}
}
int query(int x)
{
int ans=0;
while(x>0)
{
ans+=b[x];
x-=lowbit(x);
}
return ans;
}
};
BIT bit;
int main()
{
while(~scanf("%d%d",&n,&m))
{
bit.init();
int res=0,l,r,num;
for(int i=0;i<n;i++)
{
scanf("%d%d",&l,&r);
p[i]=node(l,r,0);
}
for(int i=0;i<m;i++)
{
scanf("%d",&num);
int pre=-1;
while(num--)
{
scanf("%d",&r);
q[res++]=node(pre,r,i);
pre=r;
}
q[res++]=node(pre,maxn-1,i);
}
sort(p,p+n);
sort(q,q+res);
memset(ans,0,sizeof(ans));
for(int i=0,j=0;i<res;i++)
{
while(j<n&&p[j].r<q[i].r)
bit.update(p[j].l,1),j++;
ans[q[i].id]+=bit.query(q[i].r-1)-bit.query(q[i].l);
}
for(int i=0;i<m;i++)printf("%d\n",n-ans[i]);
}
return 0;
}