Codeforces Round #216_div2_E.Valera and Queries

来源:互联网 发布:owncloud源码下载 编辑:程序博客网 时间:2024/05/21 03:29

转载注明出处  http://blog.csdn.net/moedane

 

 

传送门 http://codeforces.com/contest/369/problem/E

 

题意

给出n条线段,以及m个询问,每个询问包括cnt个点,问有多少条线段覆盖了至少一个点。

 

思路

我一开始是正着思考,想着怎样直接统计出覆盖的线段就好了。这样想的话要解决一个重复的问题,即一个线段覆盖了多个点。想直接用前缀和后缀和处理,但是样例都没法过,发现有许多问题。最后去看了别人代码才知道解法。

 

对每个询问,找出一个点都不覆盖的线段的数目。

要找出一个点都不覆盖的线段,方法是,用结构体存储询问的当前点和它左边的点,把落在该区域内的线段数目统计出来即可。对于每个询问,最左端端点可设为0,最右端可设为10^6,即问题转化为求落在这些区间内的线段的数目。

至于求这些线段数目的方法,是限制右端点小于当前询问的右端点,左端点则更新到树状数组中,即可找到当前区间内的线段数目。

先将线段排好序,离线处理询问。

 

代码

 

#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <map>#include <cctype>#define bug puts("here");using namespace std;typedef long long ll;const int maxn = 3 * 100086;const int mod = 1000000007;const double PI = atan(1.0)*4.0;int f[1000086];int Ans[maxn];struct Node{    int l,r,index;}s[maxn],q[maxn*2];bool cmp(Node a,Node b){    return a.r < b.r;}int lowbit(int x){    return x&(-x);}void update(int p,int v){    while(p < 1000006)    {        f[p] += v;        p += lowbit(p);    }    return;}int sum(int p){    int ans = 0;    while(p)    {        ans += f[p];        p -= lowbit(p);    }    return ans;}int main(){    int m,n;    scanf("%d%d",&n,&m);    int i,j;    for(i=0;i<n;i++)        scanf("%d%d",&s[i].l,&s[i].r);    int e = 0;    for(i=0;i<m;i++)    {        int cnt;        scanf("%d",&cnt);        for(j=0;j<cnt;j++)        {            scanf("%d",&q[e].r);            q[e].index = i;            if(j == 0) q[e].l = 0;            else q[e].l = q[e-1].r;            e++;        }        q[e].index = i;        q[e].l = q[e-1].r;        q[e++].r = 1000006;    }    sort(s,s+n,cmp);    sort(q,q+e,cmp);    for(i=0;i<m;i++) Ans[i] = n;    memset(f,0,sizeof(f));    j = 0;    for(i=0;i<e;i++)    {        while(j < n && s[j].r < q[i].r)        {            update(s[j].l,1);            j++;        }        Ans[q[i].index] -= sum(q[i].r - 1) - sum(q[i].l);    }    for(i=0;i<m;i++) printf("%d\n",Ans[i]);    return 0;}