HDU 5603 the soldier of love (线段树)

分析:很经典的区间覆盖问题,给 n 个线段,问m个区间 [L,R] ,共完全覆盖多少条不同的线段?

如果要完全覆盖,那么 l>=L,r<=R ,如果这个时候我们把区间加入线段的序列,按照右端点 r <script type="math/tex" id="MathJax-Element-476">r</script>来排序,用一颗线段树来维护所有的左端点,那么就是一个线段树的插入+查询操作。

此题离线做就可以了。

代码:

#include <bits/stdc++.h>

using namespace std;

#define FOR(i,x,y)  for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define fi  first
#define se  second
#define pb  push_back   
#define mp  make_pair   
#define SZ(x)   ((int)(x.size()))
#define sc(x)       scanf("%d",&x)
#define sc2(x,y)    scanf("%d%d",&x,&y)
#define sc3(x,y,z)  scanf("%d%d%d",&x,&y,&z)
#define lrt rt<<1
#define rrt     rt<<1|1
#define lson    rt<<1,l,mid
#define rson    rt<<1|1,mid,r
typedef long long LL;
typedef vector <int>    VI;
typedef pair <int,int>  PII;

const int inf = 1000010;
const int maxn = 300030;

int n,m;

struct Node{
    int l,r;
    int id;
    Node()  {}
    Node(int x,int y,int z) : l(x),r(y),id(z)   {}
    bool operator < (const Node& rhs) const{
        if(r == rhs.r)  return id > rhs.id;
        return r < rhs.r;
    }
}node[maxn<<1];

int c[inf];

int lowbit(int x)   {return x&-x;}

void modify(int x,int val){
    for(;x < inf;x += lowbit(x))    c[x] += val;
}   

int query(int x){
    int ans = 0;
    for(;x;x -= lowbit(x))  ans += c[x];
    return ans;
}

int ans[maxn];

int main(){
    //freopen("in.txt","r",stdin);
    while(~sc2(n,m)){
        FOR(i,0,inf)    c[i] = 0;
        int cnt = 0;
        FOR(i,0,n){
            int l,r;    sc2(l,r);
            node[cnt++] = Node(l,r,0);
        }
        FOR(i,1,m+1){
            int k,r;    sc(k);
            int last = 0;
            FOR(j,0,k){
                sc(r);  node[cnt++] = Node(last,r,i);
                last = r;
            }
            node[cnt++] = Node(last,inf-1,i);
        }
        sort(node,node+cnt);
        memset(ans,0,sizeof(ans));
        FOR(i,0,cnt){
            //printf("%d %d %d\n",node[i].l,node[i].r,node[i].id);
            if(!node[i].id){
                modify(node[i].l,1);
            }
            else{
                ans[node[i].id] += query(inf-1)-query(node[i].l);
                //printf("ans : %d %d ",query(inf-1),query(node[i].l));
                //printf("%d\n",ans[node[i].id]);
            }
        }
        FOR(i,1,m+1){
            printf("%d\n",n-ans[i]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值