Codeforces 369E Valera and Queries(树状数组+离线查询) *

Valera loves segments. He has recently come up with one interesting problem.

The Ox axis of coordinates has n segments, the i-th segment starts in position li and ends in position ri (we will mark it as [li, ri]). Your task is to process m queries, each consists of number cnti and a set of cnti coordinates of points located on the Ox axis. The answer to the query is the number of segments, such that each of them contains at least one point from the query. Segment [l, r] contains point q, if l ≤ q ≤ r.

Valera found the solution of this problem too difficult. So he asked you to help him. Help Valera.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 3·105) — the number of segments on the axis of coordinates and the number of queries.

Next n lines contain the descriptions of the segments. The i-th line contains two positive integers li, ri (1 ≤ li ≤ ri ≤ 106) — the borders of the i-th segment.

Next m lines contain the description of the queries, one per line. Each line starts from integer cnti (1 ≤ cnti ≤ 3·105) — the number of points in the i-th query. Then the line contains cnti distinct positive integers p1, p2, ..., pcnti (1 ≤ p1 < p2 < ... < pcnti ≤ 106) — the coordinates of points in the i-th query.

It is guaranteed that the total number of points in all queries doesn't exceed 3·105.

Output

Print m non-negative integers, where the i-th number is the response to the i-th query.

Examples

Input

3 3
1 3
4 5
6 7
3 1 4 7
2 4 5
1 8

Output

3
1
0
#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define read(x,y) scanf("%d%d",&x,&y)

const int  maxn =2e6+5;
const int N=1e6+50;
/*
题目大意:又是玩序列的题目,
给定数个线段,每个查询给出一系列的点,
要求统计每次有多少个线段覆盖这些点。

逆向思维好题,
把离线的技巧和统计完美结合。。。(参考了大佬的思路)
首先正面很难考虑则从反面出发,
就是求所有点的空隙线段,覆盖了原线段集合多少条。

这样的话离线化处理,把所有线段都放在一个集合中,
然后排序,先按左端排序,如果左端一致比较右端,
一个wa点就是,右端一致的时候比较序号(原线段集合的序号都标为-1).
按左端从大到小排列,右端从小到大排列。

之后扫描,保证每次出现的要查询的线段其左端都小于之前的,
这样用树状数组维护右端即可。
*/

int n,m,tot,x;
struct node{int l,r,mark;};//线段节点
bool cmp(node x,node y)
{
    if(x.l==y.l)
    {
        if(x.r==y.r) return x.mark<y.mark;
        return  x.r<y.r;
    }
    return x.l>y.l;
}
node seg[maxn];

int ans[maxn],dat[maxn];

int tree[maxn];
int lowbit(int x){return x&(-x);}
void add(int x,int v){for(;x<=N;tree[x]+=v,x+=lowbit(x));}
int sum(int x){int ret=0;for(;x>0;ret+=tree[x],x-=lowbit(x));return ret;}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) scanf("%d%d",&seg[i].l,&seg[i].r),seg[i].mark=-1;

    int cnt=n;
    for(int i=0;i<m;i++)
    {
        scanf("%d",&tot);

        ///memset(dat,0,sizeof(dat));
        dat[0]=0;for(int j=1;j<=tot;j++)  scanf("%d",&dat[j]);dat[tot+1]=N;

        for(int p=0,q=p+1;q<=tot+1;q++,p++)
        {
            int l=dat[p]+1,r=dat[q]-1;
            if(l>r) continue;
            seg[cnt++]=node{l,r,i};
            ///cout<<l<<" "<<r<<endl;
        }
    }
    sort(seg,seg+cnt,cmp);

    ///for(int i=0;i<cnt;i++) cout<<seg[i].l<<" "<<seg[i].r<<" "<<seg[i].mark<<endl;

    memset(ans,0,sizeof(ans));
    memset(tree,0,sizeof(tree));
    for(int i=0;i<cnt;i++)
    {
        if(seg[i].mark==-1) add(seg[i].r,1);
        else ans[seg[i].mark]+=sum(seg[i].r);
    }
    for(int i=0;i<m;i++) printf("%d\n",n-ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/81805069
今日推荐