【线段树+离散化】Mayor‘s posters

我又可以了哈哈哈哈,这题ac太开心了 

第一次写离散化的题,这个题的线段树写法对我来说也很新颖,学到了学到了

#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define xf_dycm ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long int
#define ll long long
#define ull unsigned long long
using namespace std;
const int MAXN=1e5+10;
//离散化+线段树区间修改
ll arr[MAXN<<4];
ll a[MAXN];
ll Start[MAXN],End[MAXN];
int vis[MAXN];
void Init(){
    memset(arr, 0, sizeof(arr));
    memset(a, 0, sizeof(a));
    memset(Start, 0, sizeof(Start));
    memset(End, 0, sizeof(End));
    memset(vis, 0, sizeof(vis));
}


struct Tree{
    ll l,r;
    ll color;
}tree[MAXN<<4];
void build_tree(ll i,ll L,ll R){
    tree[i].l=L;
    tree[i].r=R;
    if(tree[i].l==tree[i].r)return;
    ll mid=(L+R)/2;
    build_tree(i*2, L, mid);
    build_tree(i*2+1, mid+1, R);
}
void pushdown(ll i){
    if(tree[i].color!=0){
        tree[i*2].color=tree[i].color;
        tree[i*2+1].color=tree[i].color;
        tree[i].color=0;
    }
}

void update(ll i,ll st,ll ed,ll col){
    if(tree[i].l>=st&&tree[i].r<=ed){
        tree[i].color=col;
        return;
    }
    if(tree[i].r<st||tree[i].l>ed)return;
    pushdown(i);//如果不是整段区间都要改的,那把颜色下方到子区间里
    update(i*2, st, ed, col);
    update(i*2+1, st, ed, col);
    
    
}

ll query(ll i){
    if(tree[i].color!=0){//如果这段区间直接是有颜色标记的,说明整段区间都是这个颜色了
        if(vis[tree[i].color])return 0;
        return vis[tree[i].color]=1;
    }
    if(tree[i].l==tree[i].r)return 0;
    return query(i*2)+query(i*2+1);
    
}



signed main(){
    xf_dycm;
    ll t;
    cin>>t;
    while(t--){
        Init();
        ll n;
        cin>>n;
        ll cnt=0;
        for(ll i=1;i<=n;i++){
            cin>>Start[i]>>End[i];
            a[++cnt]=Start[i];
            a[++cnt]=End[i];
        }
        sort(a+1,a+1+cnt);
        arr[1]=a[1];ll num=1;
        for(ll i=2;i<=cnt;i++){
            if(a[i]==a[i-1]){
                continue;
            }
            else {
                arr[++num]=a[i];
            }
        }//去重
        ll now=num;
        for(ll i=1;i<now;i++){
            if(arr[i+1]-arr[i]>1){
                arr[++num]=arr[i]+1;
            }
        }//非邻数补中间数
        sort(arr+1,arr+1+num);
        build_tree(1, 1, num);
        for(ll i=1;i<=n;i++){
            ll st=lower_bound(arr+1, arr+1+num, Start[i])-arr;
            ll ed=lower_bound(arr+1, arr+1+num, End[i])-arr;
            update(1, st, ed, i);//把st到ed到部分改成颜色i
            
        }
        cout<<query(1)<<endl;
       
    }
}

          

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值