poj 2528 Mayor's posters (line segment tree)

Question:
Post a poster on a wall with a length of 10,000,000. The poster has a coverage area, and the poster that is posted later can cover the poster that was posted first. Finally asked us how many posters were displayed on the wall.
Solution:
Obviously, the range of the interval is too large. If you use the line segment tree directly, it will time out. We can discretize the interval,
for example: 1~4, 4 ~ 8, 1 ~ 8, lsh[1]=1,lsh[2]= 4;,lah[3]=8; Then the range of the first post is 1 ~ 2, the second time is 2 ~ 3, the third time is 1 ~ 3, and the final answer is 1. But such discretization is flawed, such as 1 ~8, 1 ~ 4, 6 ~8, lah[1]=1,lsh[2]=4, lsh[3]=6, lah[4]=8, The range of the first post is 1~4, the second time is 1~2, and the third time is 3~4, so the calculated answer is 2, but the actual answer is 3, so we have to make the difference in the range greater than Add another element to the element of 1. The above example is to add another 5 in 4 and 6 (of course, add others). After discretization, the line segment tree can be maintained.
Code:

#include<cstdio>
#include<iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
const int INF=1e9;
const int MAXN=1e5+5;
int lsh[MAXN];
int lt[MAXN];
int rt[MAXN];
int vis[MAXN];
struct Node
{
    
    
    int l;
    int r;
    int sum;
}node[MAXN<<2];
void push_down(int num)
{
    
    
    node[num<<1].sum=node[num].sum;
    node[num<<1|1].sum=node[num].sum;
    node[num].sum=-1;
}
void build(int left,int right,int num)
{
    
    
    node[num].l=left;
    node[num].r=right;
    node[num].sum=-1;
    if(left==right)
    {
    
    
        return;
    }
    int mid=(left+right)/2;
    build(left,mid,num<<1);
    build(mid+1,right,num<<1|1);
}
void updata(int left,int right,int val,int num)
{
    
    
    if(node[num].l>=left&&node[num].r<=right)
    {
    
    
        node[num].sum=val;
        return;
    }
    if(node[num].sum!=-1)
    {
    
    
        push_down(num);
    }
    int mid=(node[num].l+node[num].r)>>1;
    if(right<=mid)
    {
    
    
        updata(left,right,val,num<<1);
    }
    else if(left>mid)
    {
    
    
        updata(left,right,val,num<<1|1);
    }
    else
    {
    
    
        updata(left,mid,val,num<<1);
        updata(mid+1,right,val,num<<1|1);
    }
}
int ans;
void query(int num)
{
    
    
    if(node[num].sum!=-1&&!vis[node[num].sum])
    {
    
    
        ans++;
        vis[node[num].sum]=1;
        return;
    }
    if(node[num].l==node[num].r) return;
    if(node[num].sum!=-1)
    {
    
    
        push_down(num);
    }
    //int mid=(node[num].l+node[num].r)/2;
    query(num<<1);
    query(num<<1|1);
}
int main()
{
    
    
    int n;
    int t;
    scanf("%d",&t);
    while(t--)
    {
    
    
        memset(vis,0,sizeof vis);
        ans=0;
        scanf("%d",&n);
        int tot=0;
        for(int i=1;i<=n;i++)
        {
    
    
            scanf("%d %d",&lt[i],&rt[i]);
            lsh[++tot]=lt[i];
            lsh[++tot]=rt[i];
        }
        sort(lsh+1,lsh+1+tot);
        int pos=unique(lsh+1,lsh+1+tot)-lsh;
        int tt=pos-1;
        for(int i=2;i<=pos-1;i++)
        {
    
    
            if(lsh[i]-lsh[i-1]>1)
            {
    
    
                lsh[++tt]=lsh[i-1]+1;
            }
        }
        sort(lsh+1,lsh+1+tt);
        build(1,tt,1);
        for(int i=1;i<=n;i++)
        {
    
    
            int p1=lower_bound(lsh+1,lsh+1+tt,lt[i])-lsh;
            int p2=lower_bound(lsh+1,lsh+1+tt,rt[i])-lsh;
            updata(p1,p2,i,1);
        }
        query(1);
        printf("%d\n",ans);
    }
}

Guess you like

Origin blog.csdn.net/weixin_45755679/article/details/107814221