1. 程式人生 > 實用技巧 >習題: Developing Game(掃描線&線段樹)

習題: Developing Game(掃描線&線段樹)

題目

傳送門

思路

我們考慮怎麼將轉換這個限制

考慮最終的答案一定滿足一個式子,對於方案中的任意一個人都滿足\(l_i<=min\{v_i\}<=v_i<=max\{v_i\}<=r_i\)

我們把平面內的每一個點看做\((min\{v_i\},max\{v_i\})\)

把其轉換成為一個矩陣,矩陣的左下角的左邊即為\((l_i,v_i)\),右上角的座標即為\((v_i,r_i)\)

之後就是求最多有多少個矩陣重疊在一起,這就是一個掃描線的板子了

程式碼

#include<iostream>
#include<vector>
using namespace std;
namespace lst
{
    struct node
    {
        int l,r;
        int maxx,lazy,_ind;
    }tre[1200005];
    void build(int l,int r,int k)
    {
        tre[k].l=l;
        tre[k].r=r;
        if(l==r)
        {
            tre[k]._ind=l;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,k<<1);
        build(mid+1,r,k<<1|1);
        tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
        tre[k]._ind=(tre[k].maxx==tre[k<<1].maxx?tre[k<<1]._ind:tre[k<<1|1]._ind);
    }
    void push_down(int k)
    {
        tre[k<<1].lazy+=tre[k].lazy;
        tre[k<<1].maxx+=tre[k].lazy;
        tre[k<<1|1].lazy+=tre[k].lazy;
        tre[k<<1|1].maxx+=tre[k].lazy;
        tre[k].lazy=0;
    }
    void change(int l,int r,int val,int k=1)
    {
        if(l>tre[k].r||tre[k].l>r)
            return;
        if(l<=tre[k].l&&tre[k].r<=r)
        {
            tre[k].maxx+=val;
            tre[k].lazy+=val;
            return;
        }
        push_down(k);
        change(l,r,val,k<<1);
        change(l,r,val,k<<1|1);
        tre[k].maxx=max(tre[k<<1].maxx,tre[k<<1|1].maxx);
        tre[k]._ind=(tre[k].maxx==tre[k<<1].maxx?tre[k<<1]._ind:tre[k<<1|1]._ind);
    }
}
using namespace lst;
struct NODE
{
    int l,v,r;
}a[100005];
struct ls
{
    int l,r;
};
int n;
int maxx,limit,ans;
pair<int,int> li;
vector<ls> ad[300005];
vector<ls> de[300005];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].l>>a[i].v>>a[i].r;
        maxx=max(a[i].v,maxx);
        limit=max(a[i].r,limit);
        ad[a[i].l].push_back((ls){a[i].v,a[i].r});
        de[a[i].v].push_back((ls){a[i].v,a[i].r});
    }
    build(1,limit,1);
    for(int i=1;i<=maxx;i++)
    {
        for(int j=0;j<ad[i].size();j++)
            change(ad[i][j].l,ad[i][j].r,1);
        for(int j=0;j<de[i-1].size();j++)
            change(de[i-1][j].l,de[i-1][j].r,-1);
        if(tre[1].maxx>ans)
        {
            ans=tre[1].maxx;
            li=make_pair(i,tre[1]._ind);
        }
    }
    int f=1;
    cout<<ans<<'\n';
    for(int i=1;i<=n;i++)
    {
        if(a[i].l<=li.first&&li.first<=a[i].v&&a[i].v<=li.second&&li.second<=a[i].r)
        {
            if(f)
            {
                cout<<i;
                f=0;
            }
            else
                cout<<' '<<i;
        }
    }
    return 0;
}