牛客24951 Haybale Guessing

链接

点击跳转

题解

这题感觉不太好想,也可能是因为我以前没见过类似的吧

首先二分 c h e c k check check,现在问题变成了给定一些 l , r , a l,r,a l,r,a,问是否合法

首先可以发现一个问题,就是 a a a值大的区间会压缩 a a a值小的区间的“生存空间”,就比如说本来 m i n ( [ 1 , 10 ] ) = 5 min([1,10])=5 min([1,10])=5,那么 5 5 5这个数可以填在 [ 1 , 10 ] [1,10] [1,10]的任何位置。但是如果还有一个 m i n ( [ 6 , 12 ] ) = 7 min([6,12])=7 min([6,12])=7,那么 [ 6 , 10 ] [6,10] [6,10]这一段就不能填 5 5 5了。所以说 a a a值大的区间会压缩 a a a值小的区间的“生存空间”。

按照 a a a值排序,从大到小处理, a a a值大的先把他所在的那个区间给覆盖掉。然后看 a a a值小的,如果 a a a值小的无处安放了,那么就说明有冲突。如果有地方可以放,那么就不冲突。

可以用并查集辅助实现上述过程。

其实按照上述过程完全可以把方案也构造出来。

代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(i,a,b) for(i=a;i<=b;i++)
#define drep(i,a,b) for(i=a;i>=b;i--)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
struct UnionFind
{
	ll f[maxn], lft[maxn], rt[maxn];
	void init(ll n)
	{
		for(auto i=1;i<=n;i++)f[i]=i, lft[i]=rt[i]=i;
	}
	ll find(ll x){return f[x]==x?x:f[x]=find(f[x]);}
	void merge(ll x, ll y)
    {
        auto fx=find(x), fy=find(y);
        f[fx]=fy;
        if(fx!=fy)
        {
            lft[fy] = min(lft[fy],lft[fx]);
            rt[fy] = max(rt[fy],rt[fx]);
        }
    }
}uf;
struct Lisan
{
    int tmp[maxn], tot;
    void clear(){tot=0;}
    void insert(int x){tmp[++tot]=x;}
    void run()
    {
        sort(tmp+1,tmp+tot+1);
        tot=unique(tmp+1,tmp+tot+1)-tmp-1;
    }
    void lisan(int *a, int len)
    {
        for(int i=1;i<=len;i++)a[i]=lower_bound(tmp+1,tmp+tot+1,a[i])-tmp;
    }
    int lisan(int x)
    {
        return lower_bound(tmp+1,tmp+tot+1,x)-tmp;
    }
}ls;
ll L[maxn], R[maxn], A[maxn], N, Q, vis[maxn], mnl[maxn], mxl[maxn], mnr[maxn], mxr[maxn];
bool check(ll n)
{
    ll i, M=ls.tot;
    rep(i,1,M)mnl[i]=mnr[i]=linf, mxl[i]=mxr[i]=-linf;
    rep(i,1,n)
    {
        ll a = A[i];
        mnl[a] = min(mnl[a],L[i]);
        mxl[a] = max(mxl[a],L[i]);
        mnr[a] = min(mnr[a],R[i]);
        mxr[a] = max(mxr[a],R[i]);
    }
    uf.init(N);
    rep(i,1,N)vis[i]=false;
    drep(i,M,1)
    {
        if(mnl[i]==linf)continue;
        if(mxl[i]>mnr[i])return false;
        bool flag=false;
        if(!vis[mxl[i]])flag=true;
        ll p = mxl[i];
        while(uf.rt[ uf.find(p) ]<mnr[i])
        {
            ll r1 = uf.find(p), r2 = uf.find( uf.rt[r1] + 1 );
            if(!vis[r2])flag = true;
            p = uf.rt[r2];
        }
        if(flag == false)return false;
        vis[mnl[i]] = true;
        while(uf.rt[ uf.find(mnl[i]) ]<mxr[i])
        {
            ll r1 = uf.find(mnl[i]), r2 = uf.find( uf.rt[r1] + 1 );
            vis[r2] = true;
            uf.merge(r1,r2);
        }
    }
    return true;
}
int main()
{
    ll ans=0, i, j, mid, l, r;
    N=read(), Q=read();
    ls.clear();
    rep(i,1,Q)L[i]=read(), R[i]=read(), A[i]=read(), ls.insert(A[i]);
    ls.run();
    rep(i,1,Q)A[i]=ls.lisan(A[i]);
    if(check(Q)){printf("0");return 0;}
    l=1, r=Q;
    while(l<r)
    {
        ll mid = l+r>>1;
        if(check(mid))l=mid+1;
        else r=mid;
    }
    printf("%lld",r);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值