Denso Create Programming Contest 2023 (AtCoder Beginner Contest 309) F题解

文章目录

  • [Box in Box](https://atcoder.jp/contests/abc309/tasks/abc309_f)
    • 问题建模
    • 问题分析
      • 1.分析操作
      • 2.如何比较长方体判断是否有满足条件的长方体存在
      • 3.方法1使用树状数组来维护1~对应二维属性值区间内的最小三维属性值
        • 代码
      • 4.方法2使用线段树来维护1~对应二维属性值区间内的最小三维属性值
        • 代码

Box in Box

Denso Create Programming Contest 2023 (AtCoder Beginner Contest 309) F题解_第1张图片

问题建模

给定n个长方体,可以任意旋转长方体,问是否存在两个长方体其中一个长方体的长宽高都大于另一个长方体

问题分析

1.分析操作

任意旋转一个长方体,也就是将其长宽高进行交换,若所给n个长方体中存在满足要求的两个长方体,则在通过选择使其长宽高升序后,同样满足条件,则可以先对所有长方体的长宽高都排为升序。

2.如何比较长方体判断是否有满足条件的长方体存在

由于要判断两个长方体之间是否满足要求,要比较长宽高三个属性值,则可以先将所有元素按第一维的属性值大小来排序,这样就省去一维属性值的判断。然后从小到大,在考虑剩余两维属性的情况下进行判断。我们可以考虑维护一个已经遍历过元素的1~对应第二维属性值区间内的最小第三维属性值来帮助判断。

3.方法1使用树状数组来维护1~对应二维属性值区间内的最小三维属性值

代码

#include

#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N =2e5+10, INF=0x3f3f3f3f;
struct Node{
    int a,b,c;
};
Node nodes[N];
bool cmp(Node &n1,Node &n2){
    return n1.a<n2.a;
}
int tr[N];
int cnt;
int lowbit(int x){
    return x&-x;
}

int query(int x){
    int res=INF;
    for(int i=x;i;i-=lowbit(i)){
        res=min(tr[i],res);
    }
    return res;
}

void update(int k,int x){
    for(int i=k;i<=cnt;i+=lowbit(i)){
        tr[i]=min(tr[i],x);
    }
}

void solve() {
    int n;
    cin >>n;
    cnt=0;
    set<int> st;///去重
    unordered_map<int,int> mp;
    for(int i=1;i<=n;i++){
        int a[3];
        scanf("%d %d %d",&a[0],&a[1],&a[2]);
        sort(a,a+3);
        nodes[i]={a[0],a[1],a[2]};
        st.insert(a[1]);
    }
    ///使一维属性值有序
    sort(nodes+1,nodes+1+n,cmp);
    for(auto v:st){//离散化二维属性值
        mp[v]=++cnt;
    }
    memset(tr,INF,sizeof(tr));

    for(int i=1;i<=n;i++){
        int l=i;
        ///对于一维属性值相同的元素要一块查询
        while(l<n&&nodes[l+1].a==nodes[l].a)    l++;

        for(int j=i;j<=l;j++){
            if(query(mp[nodes[j].b]-1)<nodes[j].c){
                puts("Yes");
                return ;
            }
        }

        for(int j=i;j<=l;j++){
            update(mp[nodes[j].b],nodes[j].c);
        }
        i=l;
    }
    puts("No");
}   


int main() {
    int t = 1;
    //cin >> t;
    while (t--) solve();
    return 0;
}

4.方法2使用线段树来维护1~对应二维属性值区间内的最小三维属性值

代码

#include

#define x first
#define y second
#define C(i) str[0][i]!=str[1][i]
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const int N =2e5+10, INF=0x3f3f3f3f;
struct Node{
    int a,b,c;
};
Node nodes[N];
bool cmp(Node &n1,Node &n2){
    return n1.a<n2.a;
}
int cnt;

struct Seg{
    int l,r;
    int val;
}tr[N*4];

void pushup(int u){
    tr[u].val=min(tr[u<<1].val,tr[u<<1|1].val);
}

void build(int u,int l,int r){
    if(l==r)    tr[u]={l,r,INF};
    else {
        tr[u]={l,r};
        int mid=(l+r)>>1;
        build(u<<1,l,mid),build(u<<1|1,mid+1,r);
        pushup(u);
    }
}

void modify(int u,int x,int d){
    if(tr[u].l==x&&tr[u].r==x)  tr[u].val=min(tr[u].val,d);
    else {
        int mid=tr[u].l+tr[u].r>>1;
        if(x<=mid)  modify(u<<1,x,d);
        else modify(u<<1|1,x,d);
        pushup(u);
    }
}


int query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r)  return tr[u].val;

    int mid=tr[u].l+tr[u].r>>1;
    int res=INF;
    if(l<=mid)  res=query(u<<1,l,r);
    if(r>mid)   res=min(res,query(u<<1|1,l,r));
    return res;
}

void solve() {
    int n;
    cin >>n;
    cnt=0;
    set<int> st;
    unordered_map<int,int> mp;
    for(int i=1;i<=n;i++){ 
        int a[3];
        scanf("%d %d %d",&a[0],&a[1],&a[2]);
        sort(a,a+3);
        nodes[i]={a[0],a[1],a[2]};
        st.insert(a[1]);
    }
    sort(nodes+1,nodes+1+n,cmp);
    for(auto v:st){
        mp[v]=++cnt;
    }
    build(1,1,cnt);

    for(int i=1;i<=n;i++){
        int l=i;
        while(l<n&&nodes[l+1].a==nodes[l].a)    l++;

        for(int j=i;j<=l;j++){
            if(query(1,1,mp[nodes[j].b]-1)<nodes[j].c){
                puts("Yes");
                return ;
            }
        }

        for(int j=i;j<=l;j++){
            modify(1,mp[nodes[j].b],nodes[j].c);
        }
        i=l;
    }
    puts("No");
}   


int main() {
    int t = 1;
    //cin >> t;
    while (t--) solve();
    return 0;
}

你可能感兴趣的:(ABC,算法,数据结构)