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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值