D. Ezzat and Grid

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=3e5+10,mod=998244353;

vector<pair<int,int> >v[N];
int b[N<<1],siz;
int se(int u){return lower_bound(b+1,b+siz+1,u)-b;}
int tr[N<<3],ans[N],up[N],lazy[N<<3];//这块要开n的八倍是b数组的四倍; 
int ls(int u){return u<<1;}
int rs(int u){return u<<1|1;}
int se(int x,int y){return ans[x]>ans[y]?x:y;}//。。。。就那样吧。 
void push_up(int u){tr[u]=se(tr[ls(u)],tr[rs(u)]);}//不懂为什么可以直接赋值,我是每次比较了;
//对第i个数求前一行的时候加入选了第i块
//假如现在看到第i行更新第i行的每一块的时候好像都是比原先的要大,如果不大的话就可以取那个大的为现在的;
//原来如此; 
void take(int u,int t){lazy[u]=se(lazy[u],t);tr[u]=se(t,tr[u]);}

void push_down(int u,int l,int r)
{
    if(!lazy[u])return ;
    take(l,lazy[u]);
    take(r,lazy[u]);
    lazy[u]=0;
}
int quary(int u,int l,int r,int a,int b)
{    
    if(a<=l&&b>=r)return tr[u];
    int mid=l+r>>1,x=0,y=0;
    push_down(u,ls(u),rs(u));
    if(a<=mid)x=quary(ls(u),l,mid,a,b);
    if(b>mid)y=quary(rs(u),mid+1,r,a,b);
    return se(x,y);
}
void modify(int u,int l,int r,int a,int b,int t)
{
    if(a<=l&&b>=r){
        take(u,t);
        return ;
    }
    push_down(u,ls(u),rs(u));
    int mid=l+r>>1;
    if(a<=mid)modify(ls(u),l,mid,a,b,t);
    if(b>mid)modify(rs(u),mid+1,r,a,b,t);
    push_up(u);
    return ;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        v[x].push_back({y,z});
        b[i*2-1]=y;
        b[i*2]=z;
    }
    sort(b+1,b+2*m+1);
    siz=unique(b+1,b+2*m+1)-b-1;
    v[n+1].push_back({b[1],b[siz]});//就这调了我一下午,原因就是之前写了({1,siz})。。哎; 
    for(int i=1;i<=n+1;i++)
    {
        int x=0;
        for(int j=0;j<v[i].size();j++)
        {
            int l=v[i][j].first,r=v[i][j].second;
            l=se(l),r=se(r);
            v[i][j]={l,r};    //下面就懒得找了。 
            int t=quary(1,1,siz,l,r);
            if(x<ans[t])x=ans[t],up[i]=t;
        }
        ans[i]=x+1; 
        for(int j=0;j<v[i].size();j++)
            modify(1,1,siz,v[i][j].first,v[i][j].second,i);
    }    
    int i=up[n+1];
    while(i)ans[i]=0,i=up[i];//每个ans至少为1代表只选他; 
    cout<<n-ans[n+1]+1<<endl;
    for(int i=1;i<=n;i++)
        if(ans[i])cout<<i<<' ';
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李昌荣。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值