线段树 染色问题 poj 2528

题目链接

题意:有一个10000000长的墙,在墙上贴n张海报,每张海报长度相等,宽度li到ri,问贴完以后能看到几张不同的海报

思路:简单的线段树染色问题,离散化给的宽度,注意要把[li,ri]离散化为[li,ri+1),避免出错,给个样例体会一下

3

5 6

4 5

6 7

答案应该是3

题很简单,但是过题过到废,题目给的n是10000,我本来maxn=10010,然后nd数组和v数组都开得maxn,然后tree和lazy开的maxn<<3,结果疯狂re,就把nd和v都开了maxn<<2,tree和lazy开了maxn*10,结果wa了,搞了很多样例都过了,最后看了讨论区,然后把maxn开成了100010,就过了!!!!!!!!!!啊,我猜这题n值应该是1e5

//#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;

const int maxn=1e5+10;
vector<int>vc;
struct node{
    int l,r;
}nd[maxn<<2];
int v[maxn<<2],ans;
int tree[maxn*10],lazy[maxn*10];

int getid(int x){
    return lower_bound(vc.begin(),vc.end(),x)-vc.begin()+1;
}
#define rl (rt<<1)
#define rr (rt<<1|1)

void down(int rt){
    if(lazy[rt]){
        lazy[rl]=lazy[rt];
        lazy[rr]=lazy[rt];
        tree[rl]=lazy[rt];
        tree[rr]=lazy[rt];
        lazy[rt]=0;
    }
}

void up(int rt){
    if(tree[rl]==tree[rr]) tree[rt]=tree[rl];
    else if(!tree[rl] || !tree[rr]) tree[rt]=tree[rl]+tree[rr];
    else tree[rt]=-1;
}

void update(int x,int y,int z,int l,int r,int rt){
    if(x<=l && r<=y){
        tree[rt]=z;
        lazy[rt]=z;
        return;
    }
    down(rt);
    int mid=(l+r)>>1;
    if(x<=mid) update(x,y,z,l,mid,rl);
    if(y>mid) update(x,y,z,mid+1,r,rr);
    up(rt);
}

void query(int l,int r,int rt){
    if(tree[rt]>0){
        if(!v[tree[rt]]) ans++;
        v[tree[rt]]++;
        return;
    }
    if(l==r) return;
    if(!tree[rt]) return;
    down(rt);
    int mid=(l+r)>>1;
    query(l,mid,rl);
    query(mid+1,r,rr);
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        memset(tree,0,sizeof(tree));
        memset(v,0,sizeof(v));
        memset(lazy,0,sizeof(lazy));
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&nd[i].l,&nd[i].r);
            nd[i].r++;
            vc.push_back(nd[i].l);
            vc.push_back(nd[i].r);
        }
        sort(vc.begin(),vc.end()),vc.erase(unique(vc.begin(),vc.end()),vc.end());
        int l=vc.size();
        for(int i=1;i<=n;i++) update(getid(nd[i].l),getid(nd[i].r)-1,i,1,l,1);
        ans=0;
        query(1,l,1);
        printf("%d\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值